20190802_Nginx基础
20190802_Nginx基础
关于中间件比较通俗易懂的解释
个人理解:将具体业务和底层逻辑解耦的组件。
大致的效果是:需要利用服务的人(前端写业务的),不需要知道底层逻辑(提供服务的)的具体实现,只要拿着中间件结果来用就好了。
介于操作系统和应用程序之间的产品,中间件简单解释,你可以理解为面向信息系统交互,集成过程中的通用部分的集合,屏蔽了底层的通讯,交互,连接等复杂又通用化的功能,以产品的形式提供出来,系统在交互时,直接采用中间件进行连接和交互即可,避免了大量的代码开发和人工成本。其实,理论上来讲,中间件所提供的功能通过代码编写都可以实现,只不过开发的周期和需要考虑的问题太多,逐渐的,这些部分,以中间件产品的形式进行了替代。
比如常见的消息中间件,即系统之间的通讯与交互的专用通道,类似于邮局,系统只需要把传输的消息交给中间件,由中间件负责传递,并保证传输过程中的各类问题,如网络问题,协议问题,两端的开发接口问题等均由消息中间件屏蔽了,出现了网络故障时,消息中间件会负责缓存消息,以避免信息丢失。相当于你想给美国发一个邮包,只需要把邮包交给邮局,填写地址和收件人,至于运送过程中的一系列问题你都不需要关心了。
通俗易懂的例子:我开了一家炸鸡店(业务端),然而周边有太多屠鸡场(底层),为了成本我肯定想一个个比价,再综合质量挑选一家屠鸡场合作(适配不同底层逻辑)。由于市场变化,合作一段时间后,或许性价比最高的屠鸡场就不是我最开始选的了,我又要重新和另一家屠鸡场合作,进货方式、交易方式等等全都要重来一套(重新适配)。然而我只想好好做炸鸡,有性价比高的肉送来就行。于是我找到了一个专门整合屠鸡场资源的第三方代理(中间件),跟他谈好价格和质量后(统一接口),从今天开始,我就只需要给代理钱,然后拿肉就行。代理负责保证肉的质量,至于如何根据实际性价比,选择不同的屠鸡场,那就是代理做的事了。
--------------------------------------------------------------------------------------------------------------------------------------------
在网站后台,往往存在很多应用服务,对应的是操作系统驱动硬件提供对应的服务。在很多应用的情况下,应用与应用之间直接调用,或应用直接与操作系统交互,会导致层次化的应用不够隔离,代码耦合程度高。此时需要中间件代理处理一些请求,让应用只负责业务的逻辑处理。
大型网站中,中间件一个个串联,使得网站层次性更高,维护更简单。
中间件还有web请求负载均衡,http请求缓存服务,安全应用防控等作用。
Nginx简述
Nginx是一个开源且高性能、可靠的HTTP中间件(企业应用场景最多)、代理服务。
常见HTTP服务:HTTPD,IIS,GWS(不对外开放)
Nginx特性优点:
- IO多路复用epoll:IO多路复用解决方案有select、poll和epoll,epoll是select和poll的增强版本,更灵活,没有描述符限制,效率更高
- 轻量级:功能模块少,代码模块化
- CPU亲和(affinity,一种把CPU核心和nginx工作进程绑定的方式):通过把每个worker进程固定在一个cpu上执行,减少切换cpu的cache miss,获得更好性能
- 采用sendfile使得nginx处理静态文件的效率非常有优势:sendfile机制,静态文件直接通过内核空间传递给socket,而不需要进一步经过用户空间的逻辑性的处理。
Nginx环境配置以及安装
安装Nginx前的环境配置:
- 系统能上外网,确认yum可用,需要通过yum来安装装一些编译环境和实用软件;
- 禁用iptables,firewall防火墙;
- 禁用SELinux
cd /opt mkdir app dpwnload logs work backup yum install -y gcc gcc-c++ autoconf pcre pcre-devel make automake yum install -y wget httpd-tools vim
配置好环境后,到Nginx官网:http://nginx.org/en/linux_packages.html#RHEL-CentOS,复制对应系统的yum源参数,其中nginx-stable是稳定版,nginx-mainline为开发版,实际应用中当然选稳定版。
vim /etc/yum.repos.d/nginx.repo [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key
安装nginx:
yum install -y nginx
#查看nginx版本 nginx -v
#查看nginx编译参数 nginx -V
#启动nginx服务
nginx
Nginx的目录和配置语法
查看nginx安装目录:rpm -ql nginx
路径 |
类型 |
作用 |
/etc/logrotate.d/nginx |
配置文件 |
Nginx日志轮转,用于logrotate服务的日志切割 |
/etc/nginx /etc/nginx/nginx.conf /etc/nginx/conf.d /etc/nginx/conf.d/default.conf |
目录、配置文件 |
Nginx主配置文件。默认配置下nginx.conf中加载了default.conf |
/etc/nginx/fastcgi_params /etc/nginx/uwsgi_params /etc/nginx/scgi_params |
配置文件 |
cgi配置相关,fastcgi配置 |
/etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/win-utf |
配置文件 |
编码转换映射转化文件 |
/etc/nginx/mime.types |
配置文件 |
设置http协议的Content-Type与拓展名对应关系 |
/usr/lib/systemd/system/nginx-debug.service /usr/lib/systemd/system/nginx.service /etc/sysconfig/nginx /etc/sysconfig/nginx-debug |
配置文件 |
用于配置系统守护进程管理器管理方式 |
/usr/lib64/nginx/modules /etc/nginx/modules |
目录 |
Nginx模块目录 |
/usr/sbin/nginx /usr/sbin/nginx-debug |
命令 |
Nginx服务的启动管理的终端命令 |
/usr/share/doc/nginx-1.16.0 /usr/share/doc/nginx-1.16.0/COPYRIGHT /usr/share/man/man8/nginx.8.gz |
文件、目录 |
Nginx的手册和帮助文件 |
/var/cache/nginx |
目录 |
Nginx的缓存目录 |
/var/log/nginx |
目录 |
Nginx的日志目录 |
查看Nginx安装编译参数:nginx -V
编译选项 |
作用 |
--prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock |
安装目的目录或路径 |
--http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp |
执行对应模块时,Nginx所保留的临时性文件 |
--user=nginx --group=nginx |
设定Nginx进程启动的用户和用户组 |
--with-cc-opt=parameters |
设置额外的参数将被添加到CFLAGS变量 |
--with-ld-opt=parameters |
设置附加的参数,链接系统库 |
完整的nginx配置文件结构
一个http可以有多个server,一个server可以有多个location。
nginx服务会先读取主配置文件nginx.conf,默认的nginx.conf的最后有一句“include /etc/nginx/conf.d/*.conf”,即会读取该目录下的所有conf文件。
nginx服务主配置文件/etc/nginx/nginx.conf的参数解释:
user nginx; #指定Nginx的worker进程运行用户以及用户组,默认为nginx worker_processes 1; #指定Nginx要开启的进程数,一般与cpu核心数一样即可 error_log /var/log/nginx/error.log warn; #用来定义全局错设日志文件的路径和日志名称。日志输出级别有debug,info,notice,warn,error,crit可供选择,其中debug输出日志最为详细,面crit输出日志最少。 pid /var/run/nginx.pid; #用来指定进程id的存储文件位置。 events { #设定nginx的工作模式及连接数上限 worker_connections 1024; #设置nginx每个进程最大的连接数,默认是1024,所以nginx最大的连接数max_client=worker_processes * worker_connections。进程最大连接数受到系统最大打开文件数的限制,需要设置ulimit。
#use epoll #指定nginx的工作模式(这里是epoll,epoll是多路复用IO(I/O Multiplexing)中的一种方式),nginx支持的工作模式有select ,poll,kqueue,epoll,rtsig,/dev/poll。其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,对于linux系统,epoll是首选。 } #以上是对nginx全局属性的配置 #下面是nginx对http服务相关属性设置 http { include /etc/nginx/mime.types; #include包含某文件的设定,减少主配置文件的复杂度,相当于把部分设置放在别的地方,然后在包含进来,保持主配置文件的简洁。 default_type application/octet-stream; #默认文件类型,当文件类型未定义时候就使用这类设置。 #log_format:指定nginx日志的格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #开启sendfile,开启高效文件传输模式(zero copy 方式),避免内核缓冲区数据和用户缓冲区数据之间的拷贝。 #tcp_nopush on; keepalive_timeout 65; #客户端连接超时时间 #gzip on; #是否开启gzip模块 include /etc/nginx/conf.d/*.conf; #包含指定路径下所有conf文件的配置 }
nginx服务子配置文件/etc/nginx/conf.d/default.conf配置参数解释:
server { listen 80; #虚拟主机的服务端口 server_name localhost; #指定ip或域名,多个域名用逗号分开 #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { #地址匹配设置,支持正则匹配,也支持条件匹配,这里是默认请求地址,用户可以location命令对nginx进行动态和静态网页过滤处理 root /usr/share/nginx/html; #虚拟主机的网页根目录 index index.html index.htm; #默认访问首页文件 } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; #若出现500等错误,则跳转到下面的location配置路径下的50x.html location = /50x.html { root /usr/share/nginx/html; #错误页面的路径 } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; #将以php为后缀的文件转发到 FastCGI处理. 使用FastCGI默认配置。本地9000端口处理 # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
修改静态内容无需重启nginx服务,但修改了conf配置文件则需要重启服务方能生效,也可以柔和重启
vim /etc/nginx/conf.d/default.conf 17 error_page 500 502 503 504 404 /50x.html; #添加404错误,出现404错误时跳转到50x.html nginx -t #检查nginx配置文件是否有语法问题 nginx -s reload #柔和重启,无需关闭服务即可加载最新的配置
Nginx日志_log_format
Nginx日志主要分为两种:访问日志(access.log)和错误日志(error.log)。日志开关在Nginx配置文件(/etc/nginx/nginx.conf)中设置,两种日志都可以选择性关闭,默认都是打开的。
访问日志
主要记录客户端访问Nginx的每一个请求,格式可以自定义。通过访问日志,可以得到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息。Nginx中访问日志相关指令主要有两条:
(1)log_format用来设置日志格式,也就是日志文件中每条日志的格式,具体说明:
- 语法:log_format name(格式名称) type(格式样式)
- 支持模块:http
nginx.conf中默认的log_format 格式样式的变量含义:
- $remote_addr:远程客户端的IP地址。
- -:空白,用一个“-”占位符替代,历史原因导致还存在。
- $remote_user:远程客户端用户名称,用于记录浏览者进行身份验证时提供的名字,若没有登录就是空白(变量值为空,在日志输出结果为一个"-"符号)。
- [$time_local]:访问的时间与时区,如[04/Aug/2019:11:13:43 +0800],时间信息最后的"+0800"表示服务器所处时区位于UTC之后的8小时。
- $request:请求的URI(即ip地址后的/XXX/XXX.html)和HTTP协议(有版本号),这是整个PV日志记录中最有用的信息,记录服务器收到一个什么样的请求
- $status:记录请求返回的http状态码,比如成功是200。
- $body_bytes_sent:发送给客户端的文件主体内容的大小,比如899,可以将日志每条记录中的这个值累加起来以粗略估计服务器吞吐量。
- $http_referer:记录从哪个页面链接访问过来的。
- $http_user_agent:客户端浏览器信息
- $http_x_forwarded_for:客户端的真实ip,通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
HTTP请求变量:http请求的request头和response头,可以用curl命令看http请求响应报文的详细内容。
- arg_PARAMETER:HTTP请求中某个参数的值,如/index.php?site=www.ttlsa.com,可以用$arg_site取得www.ttlsa.com
- http_HEADER:客户端向服务端的request请求header,如user_agent,host,accept
- sent_http_HEADER:服务端返回给客户端的response响应header,如server,date,content_type,content_length等
(2)access_log用来指定日志文件的存放路径(包含日志文件名)、格式和缓存大小,具体说明:
- 语法:access_log path(存放路径) [format(自定义日志格式名称) [buffer=size | off]]
- 支持模块:http、server、location
如果想关闭日志,可以如下:access_log off;
需要注意的是:Nginx进程设置的用户和组必须对日志路径有创建文件的权限,否则会报错。
Nginx支持为每个location指定强大的日志记录。同样的连接可以在同一时间输出到不止一个的日志中。
错误日志
主要记录客户端访问Nginx出错时的日志,格式不支持自定义。通过错误日志,可以得到系统某个服务或server的性能瓶颈等。
错误日志由指令error_log来指定,具体格式如下:error_log path(存放路径) level(日志等级)
path含义同access_log,level表示日志等级,具体如下:[ debug | info | notice | warn | error | crit ]
从左至右,日志详细程度逐级递减,即debug最详细,crit最少。
需要注意的是:error_log off并不能关闭错误日志,而是会将错误日志记录到一个文件名为off的文件中。
正确的关闭错误日志记录功能的方法如下:error_log /dev/null;把存储日志路径定义为“黑洞”,即不会记录错误日志。
Nginx模块
--with-http_stub_status_module:nginx的客户端状态。在server块里面添加如下location,浏览器访问http://ip地址/mystatus,显示客户端状态信息
location /mystatus {
stub_status; #可以使用在server块和location块中
}
--with-http_random_index_module:目录中选择一个随机主页。在server块里面添加如下location,浏览器访问http://ip地址,随机显示location定义路径下的一个html文件作为主页,可刷新页面测试。
该模块只能在location为“/”的情况下生效,且隐藏文件不会作为随机主页的对象。
location / { root /opt/app/code; #在此路径下创建若干个html文件 random_index on; #开启随机主页功能,只能用在location块中 #index index.html index.htm; }
--with-http_sub_module:HTTP内容替换。在server块里面添加如下location,浏览器访问http://ip地址,可以对页面的指定字符串内容替换为指定内容。
该模块只能在location为“/”的情况下生效。
location / { root /usr/share/nginx/html; #主页文件的内容为fuck you fuck me index index.html index.htm; sub_filter 'fuck' 'FUCK'; #fuck替换为FUCK,可用在http,server,location中 sub_filter_once off; #替换文本中所有匹配的fuck为FUCK(默认为on,只会替换按第一个fuck)。可用在http,server,location中 }
Nginx的请求限制
HTTP请求建立在一次TCP连接的基础上。一次TCP连接至少可以产生一次HTTP请求,HTTP1.1版本以后,建立一次TCP连接可以发送多次HTTP请求。
连接频率限制:limit_conn_module
#语法 Syntax: limit_conn_zone key zone=name:size; Default: — Context: http Syntax: limit_conn zone number; Default: — Context: http, server, location
请求频率限制:limit_req_module
#语法 Syntax: limit_req_zone key zone=name:size rate=rate; Default: — Context: http Syntax: limit_req zone=name [burst=number] [nodelay]; Default: — Context: http, server, location
例:
http { # ...其它代码省略... # 开辟一个10m的连接空间,命名为conn_name limit_conn_zone $binary_remote_addr zone=conn_name:10m; # 开辟一个10m的请求空间,命名为req_zone。同一个IP发送的请求,平均每秒只处理一次 limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s; server { ... location / { ... #服务器每次只允许一个IP地址连接 #limit_conn con_zone 1; #limit_req zone=req_zone; #当客户端请求超过指定次数,最多宽限3次请求,并延迟处理,1秒1个请求 #limit_req zone=req_zone burst=3; #当客户端请求超过指定次数,最多宽限次请求,并立即处理。 #limit_req zone=req_zone burst=3 nodelay; } } }
具体可以用ab压力测试命令进行测试:ab -n 50 -c 20 http://ip地址。n表示请求数,c表示同时并发请求数。
Nginx的访问控制
基于IP的访问控制:http_access_module
语法:#address表示IP地址,CIDR表示网段,unix表示Socket方式,all代表所有
Syntax: allow address | CIDR | unix: | all; Default: — Context: http, server, location, limit_except Syntax: deny address | CIDR | unix: | all; Default: — Context: http, server, location, limit_except
用法:在nginx配置文件中的 server 下配置
server { # ...其它代码省略... location ~ ^/index_1.html { root /usr/share/nginx/html; deny 151.19.57.60; # 拒绝这个IP访问 allow all; # 允许其他所有IP访问 } location ~ ^/index_2.html { root /usr/share/nginx/html; allow 151.19.57.0/24; # 允许IP 151.19.57.* 访问 deny all; # 拒绝其他所有IP访问 } }
http_access_module局限性:当客户端通过代理访问时,nginx的remote_addr获取的是代理的IP,此时用http_access_module就不是对客户端的精准控制了,所有通过该代理IP访问nginx服务的客户端都会被配置规则所控制。
http_x_forwarded_for:
可以记录客户端及所有中间代理的IP,格式:http_x_forwarded_for = Client IP, Proxy1 IP, Proxy2 IP, ...
基于用户的登录认证:http_auth_basic_module
语法:
Syntax: auth_basic string | off; Default: auth_basic off; Context: http, server, location, limit_except Syntax: auth_basic_user_file file; Default: — Context: http, server, location, limit_except
用法:
1.用htpasswd命令生成账号密码文件(没有该命令则安装httpd-tools)
yum -y install httpd-tools htpasswd -c /etc/nginx/auth_conf kamin #kamin是用户名(随便起)
2.在nginx配置文件中的 server 下配置
server { # ...其它代码省略... location ~ ^/index.html { root /usr/share/nginx/html; auth_basic "Auth access! Input your password!"; #提示字符串 auth_basic_user_file /etc/nginx/auth_conf; #以生成的auth_conf文件中的用户密码作为认证条件 } }
配置好并重启nginx服务后,浏览器访问会弹出用户密码认证输入框。
http_auth_basic_module 局限性:用户信息依赖文件方式,操作管理效率低下。