nginx简介及相关知识点
一、NGINX相关简介
1.NGINX简介
一款轻量级的网页服务器、反向代理服务器以及电子邮件代理服务器。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。起初是供俄国大型的门户网站及搜索引擎Rambler(俄语:Рамблер)使用。此软件在BSD-like协议下发行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris以及Microsoft Windows等操作系统中运行。
世界第二大web服务器软件,以高并发、低消耗著称,源自于俄罗斯,创建者Igor(伊戈尔),2004年开源,最早以代理服务器的身份出现,2015成立nginx公司,2019年以6.7亿被F5 Networks公司收购。
2.代理服务
可简单的分为正向代理和反向代理。
(1)正向代理:用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送到代理服务器上,然后由代理服务器去访问Web服务器, 并将Web服务器的Response回传给客户端;
(2)反向代理:如果局域网向Internet提供资源,并让Internet上的其他用户可以访问局域网内资源,也可以设置一个代理服务器,它提供的服务就是反向代理,反向代理服务器接受来自Internet的连接,然后将请求转发给内部网络上的服务器,并将Response回传给Internet上请求连接的客户端。
3.nginx反向代理
Web服务器的调度器
(1)反向代理(Reverse Proxy)方式指以代理服务器来接受客户端的连接请求,然后将请求转发给网络上的web服务器(可能是apache、nginx、tomcat、iis等),并将从web服务器上得到的结果返回给请求连接的客户端,此时代理服务器对外就表现为一个服务器。
可以看出:反向代理服务器代理网站Web服务器接收http请求,对请求进行转发。nginx作为反向代理服务器可以根据用户请求的内容把请求转发给后端不同的web服务器,例如静动分离,再例如在nginx上创建多个虚拟主机,可以做到在浏览器中输入不同域名(url)时访问后端的不同web服务器或web群集。
(2)反向代理的作用
①保护网站安全:任何来自Internet的请求都必须先经过代理服务器;
②通过配置缓存功能加速Web请求:可以缓存真实Web服务器上的某些静态资源,减轻真实Web服务器的负载压力;
③实现负载均衡:充当负载均衡服务器均衡地分发请求,平衡集群中各个服务器的负载压力;
二、各种代理服务器的比较
正向:squid
反向:squid最古老的代理服务器
1.LVS的优缺点
优点 | 缺点 |
---|---|
抗负载能力强、工作在网络4层之上,仅作分发之用; | 不支持正则表达式处理,不能做动静分离; |
配置性比较低,既是缺点也是优点,简单不易出错; | 如果网站应用比较庞大,LVS/DR+Keepalived实施比较复杂; |
工作稳定,抗负载能力很强,有完整的双机热备方案,如LVS(DR)+Keepalived; | |
无流量,LVS只分发请求,而流量并不从它本身出去; | |
应用范围比较广,几乎支持所有应用; |
2.nginx的优缺点
优点 | 缺点 |
---|---|
工作在七层之上,针对HTTP做分流策略,正则规则比haproxy更灵活; | 适应范围较小,仅能支持http、https、Email协议; |
对网络的稳定性依赖小; | 对后端服务器的健康检查,只支持通过端口检测,不支持url来检测; |
安装配置简单; | |
高负载、高并发、低消耗; | |
不仅能做代理,还可以做web服务器; | |
可以缓存静态网页和图片; | |
社区活跃,第三方模块非常多; |
3.haproxy的优缺点
优点 | 缺点 |
---|---|
支持虚拟主机,可以工作在4、7层(支持多网段); | 不支持POP/SMTP协议; |
支持Session的保持、Cookie的引导、支持通过获取指定的url来检测后端服务器的状态; | 不支持SPDY协议; |
跟LVS类似,本身就只是一款负载均衡软件,效率上比Nginx有更出色的负载均衡速度,在并发处理上也优于Nginx; | 不支持HTTP cache功能; |
支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡; | 重载配置的功能需要重启进程; |
负载均衡策略非常多,具体有8种; | 多进程模式支持不够好; |
三、nginx详解
1.Nginx的核心特点
(1)跨平台:Nginx可以在大多数OS编译运行,而且也有Windows版本;
(2)配置异常简单:非常容易上手;
(3)非阻塞、高并发连接:官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数;
这得益于Nginx使用了最新的epoll模型。
(4)事件驱动:通信机制采用epoll模型,支持更大的并发连接;
(5)Master/Worker结构:一个master进程,生成一个或多个worker进程;
(6)内存消耗小:处理大并发的请求内存消耗非常小。
在3万并发连接下,开启的10个Nginx进程才消耗150M内存(15M*10=150M);
(7)内置健康检查功能:如果Nginx代理的后端的某台Web服务器宕机了,不会影响前端访问;
(8)节省带宽:支持Gzip压缩,可以添加浏览器本地缓存的Header头;
(9)稳定性高:用于反向代理,宕机的概率微乎其微。
2.http请求的基本过程
对于Web服务器来说,首先看一个请求的基本过程:建立连接—接收数据—发送数据,在系统底层看来:上述过程在系统底层就是读写事件。
如果采用阻塞调用的方式:当读写事件没有准备好时,那么就只能等待,当前线程被挂起,等事件准备好才能进行读写事件。
如果采用非阻塞调用的方式:事件马上返回,告诉你事件还没准备好,过会再来。过一会,再检查一下事件,直到事件准备好了为止。在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你要不时地过来检查一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
非阻塞调用通过不断检查事件的状态来判断是否进行读写操作,这样带来的开销很大,因此就有了异步非阻塞的事件处理机制。这种机制让你可以同时监控多个事件,调用他们是非阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好就返回。这种机制解决了上面阻塞调用与非阻塞调用的两个问题。
以epoll模型为例
当事件没有准备好时,就放入epoll(队列)里面。如果有事件准备好了,那么就去处理。这样就可以并发处理大量的请求了,当然,这里的并发请求,是指未处理完的请求。线程只有一个,所以同时能处理的请求当然只有一个,只是在请求之间进行不断地切换,切换也是因为异步事件未准备好,而主动让出的。这里的切换没有任何代价,可以理解为循环处理多个准备好的事件。
多线程方式相比,这种事件处理方式有很大的优势,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级,并发数再多也不会导致无谓的资源浪费(上下文切换)。对于apache服务器,每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求。这对操作系统来说,是个不小的挑战。因为线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去,从而导致在高并发场景下性能下降严重。
总结:通过异步非阻塞的事件处理机制,Nginx实现由进程循环处理多个准备好的事件,从而实现高并发和轻量级。
Master/Worker结构
注意:Master-Worker设计模式主要包含两个主要组件Master和Worker,Master维护着Worker队列,将请求下发到多个Worker并行执行,Worker主要进行实际逻辑计算,并将结果返回给Master。
nginx采用这种进程模型有什么好处?
采用独立的进程,互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,Master进程则很快重新启动新的Worker进程。当然,Worker进程的异常退出,肯定是程序有bug了,异常退出会导致当前Worker上的所有请求失败,不过不会影响到所有请求,所以降低了风险。
3.nginx的基础特性
(1)模块化设计,较好的扩展性;
(2)高可靠性
(3)支持热部署,不停机更新配置文件,升级版本,更换日志文件;
(4)低内存消耗,10000个keep-alive下的非活动连接,仅需2.5M内存;
(5)event-driven(事件驱动),aio(异步非阻塞),mmap(内存映射),sendfile(代理转发)。
4.nginx基本功能
(1)静态资源的web服务器;
(2)http协议的反向代理;
(3)fastcgi、uWSGI(python);
(4)pop3/imap4邮件反向代理;
(5)模块化、zip、ssl等模块。
5.nginx进程结构
master的作用 | worker的作用 |
---|---|
读取nginx配置文件,验证有效性和正确性; | 接受处理客户的请求(按模块区分); |
建立、绑定和关闭socket连接; | I/O调用; |
接受外界指令,比如重启、开、关服务; | 与后端服务器通信; |
不中断服务,平滑升级; | 缓存数据; |
处理perl脚本; | 接受主程序的指令,发送请求结果; |
6.nginx模块
核心模块:
core module
标准模块:
ngx_http_*
ngx_mail_*
ngx_upstream_*
第三方模块:
四、nginx配置反向代理
配置nginx作为反向代理和负载均衡,同时利用其缓存功能,将静态页面缓存,以达到降低后端服务器连接数的目的,并检查后端web服务器的健康状况。
1.环境准备
关防火墙和selinux。
源码包下载:
http://nginx.org/en/download.html(mainline:开发版 stable:稳定版)
rpm包的yum源:
http://nginx.org/packages/centos/7/x86_64/
2.安装前提软件
[root@nginx ~]# yum -y install gcc gcc-c++ make libtool zlib zlib-devel pcre pcre-devel openssl openssl-devel
注意
(1)结合proxy和upstream模块实现后端web负载均衡;
(2)使用proxy模块实现静态文件缓存;
(3)结合自带的ngx_http_proxy_module模块和ngx_http_upstream_module模块实现后端服务器的健康检查,也可以使用第三方模块nginx_upstream_check_module;
(4)使用nginx-sticky-module扩展模块实现Cookie会话黏贴(保持会话);
(5)使用ngx_cache_purge实现更强大的缓存清除功能;
nginx-sticky-module和ngx_cache_purge模块都属于第三方扩展模块,需要提前下好源码,然后编译时通过–add-moudle=src_path一起安装。
3.复制nginx和缓存包到/usr/src目录下解压
[root@nginx ~]# groupadd www #添加www组
[root@nginx ~]# useradd -g www www -s /sbin/nologin #创建nginx运行账户www并加入到www组,不允许www用户直接登录系统
[root@nginx ~]# cd /usr/src
[root@nginx src]# tar zxf nginx-goodies-nginx-sticky-module-ng-08a395c66e42.tar.gz
[root@nginx src]# tar zxf ngx_cache_purge-2.3.tar.gz
[root@nginx src]# tar zxf nginx-1.12.0.tar.gz
4.编译安装nginx
[root@nginx src]# cd nginx-1.12.0
[root@nginx nginx-1.12.0]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --with-http_gzip_static_module --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-pcre --add-module=../ngx_cache_purge-2.3 --with-http_flv_module --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42 && make && make install
注意:nginx的所有模块必须在编译的时候添加,不能在运行的时候动态加载。
5.优化nginx程序的执行路径
[root@nginx nginx-1.12.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@nginx nginx-1.12.0]# mkdir -p /var/tmp/nginx
[root@nginx nginx-1.12.0]# chown -R www:www /var/tmp/nginx
[root@nginx nginx-1.12.0]# mkdir -p /var/tmp/nginx/client
[root@nginx nginx-1.12.0]# mkdir -p /var/tmp/nginx/proxy
[root@nginx nginx-1.12.0]# mkdir -p /var/tmp/nginx/fcgi
6.编写nginx服务脚本并设置开机自启
[root@nginx nginx-1.12.0]# vim /etc/init.d/nginx
#!/bin/bash
#chkconfig: 2345 99 20
#description: Nginx Service Control Script
PROG="/usr/local/nginx/sbin/nginx"
PIDF="/usr/local/nginx/logs/nginx.pid"
case "$1" in
start)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
echo "Nginx service already running."
else
$PROG -t &> /dev/null
if [ $? -eq 0 ] ; then
$PROG
echo "Nginx service start success."
else
$PROG -t
fi
fi
;;
stop)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
kill -s QUIT $(cat $PIDF)
echo "Nginx service stop success."
else
echo "Nginx service already stop"
fi
;;
restart)
$0 stop
$0 start
;;
status)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
echo "Nginx service is running."
else
echo "Nginx is stop."
fi
;;
reload)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
$PROG -t &> /dev/null
if [ $? -eq 0 ] ; then
kill -s HUP $(cat $PIDF)
echo "reload Nginx config success."
else
$PROG -t
fi
else
echo "Nginx service is not run."
fi
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
[root@nginx nginx-1.12.0]# chmod +x /etc/init.d/nginx
[root@nginx nginx-1.12.0]# chkconfig --add nginx
[root@nginx nginx-1.12.0]# chkconfig nginx on
[root@nginx nginx-1.12.0]# service nginx start
注意:如果你想在已安装好的nginx上添加第三方模块,则需要重新编译,但为了不覆盖原有的配置,不要make install,而是直接拷贝可执行文件:
[root@nginx nginx-1.12.0]# nginx –V
[root@nginx nginx-1.12.0]# ./configure --add-module=…… #你的第三方模块
[root@nginx nginx-1.12.0]# make #后面不要make install,改为手动拷贝,先备份
[root@nginx nginx-1.12.0]# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
[root@nginx nginx-1.12.0]# cp objs/nginx /usr/local/nginx/sbin/nginx
7.配置nginx反向代理:反向代理+负载均衡+健康探测
查看nginx加载的模块
[root@www ~]## nginx -V
nginx version: nginx/1.10.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx1.10 --user=www --group=www --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --with-http_gzip_static_module --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-pcre --add-module=../ngx_cache_purge-2.3 --with-http_flv_module --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42
注意:nginx的所有模块必须在编译的时候添加,不能再运行的时候动态加载。
8.查看版本
[root@nginx nginx-1.12.0]# nginx -v
nginx version: nginx/1.12.0
(1)nginx-sticky-module模块
通过cookie黏贴的方式将来自同一个客户端的请求发送到同一个后端服务器上处理,一定程度上可以解决多个backend servers的session同步问题。因为不再需要同步,而RR轮询模式必须要考虑session同步的实现。
另外内置的ip_hash也可以实现根据客户端IP来分发请求,但它很容易造成负载不均衡的情况,而如果nginx前面有CDN网络或者来自同一局域网的访问,它接收的客户端IP是一样的,容易造成负载不均衡现象。
nginx-sticky-module的cookie过期时间,默认浏览器关闭就过期。
这个模块并不合适不支持Cookie或手动禁用了cookie的浏览器,此时默认sticky就会切换成RR。它不能与ip_hash同时使用。
upstream backend {
server 192.168.229.140:80 weight=1;
server 192.168.229.141:80 weight=1;
sticky;
}
配置起来超级简单,一般来说一个sticky指令就够了。
相关信息可以查看官方文档https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng
(2)load-balance其它调度方案
轮询(默认):
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。
Weight指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况。
ip_hash:
每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
当然如果这个节点不可用了,会发到下个节点,而此时没有session同步的话就注销掉了。
least_conn:
请求被发送到当前活跃连接最少的realserver上,会考虑weight的值。
url_hash:
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。
Nginx本身不支持url_hash,如果需要使用这种调度算法,必须安装Nginx的hash软件包nginx_upstream_hash。
fair:
这是比上面两个更加智能的负载均衡算法。
此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
Nginx本身不支持fair,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
(3)负载均衡与健康检查
严格来说,nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的ngx_http_proxy_module模块和ngx_http_upstream_module模块中的相关指令来完成当后端节点出现故障时,自动切换到下一个节点来提供访问。
http {
include mime.types;
default_type application/octet-stream;
定位到http模块在这下面添加内容如下:
upstream backend {
server 192.168.229.140:80 weight=1;
server 192.168.229.141:80 weight=1;
sticky;
}
server {
……
location / {
定位到server模块这里添加下面内容:
proxy_pass http://backend;
}
}
……
}
也可以这样添加
http {
include mime.types;
default_type application/octet-stream;
定位到http模块在这下面添加内容如下:
upstream backend {
sticky;
server 192.168.229.140:80 weight=1 max_fails=2 fail_timeout=10s;
server 192.168.229.141:80 weight=1 max_fails=2 fail_timeout=10s;
}
server {
……
location / {
定位到server模块这里添加下面内容:
proxy_pass http://backend;
}
……
}
注意:http模块中upstream后面跟的名字和下面server模块中添加的proxy后面的名字要一致。
相关参数解释
weight:轮询权值也是可以用在ip_hash的,默认值为1;
max_fails:允许请求失败的次数,默认为1。
当超过最大次数时,返回proxy_next_upstream模块定义的错误;
fail_timeout:两层含义。
一是在10s时间内最多容许2次失败;
二是在经历了2次失败以后,10s时间内不分配请求到这台服务器。
可以进行访问验证:访问前端nginx,它会把请求转发到后端的web服务器。
(4)nginx的proxy缓存使用
缓存也就是将js、css、image等静态文件从后端服务器缓存到nginx指定的缓存目录下,既可以减轻后端服务器负担,也可以加快访问速度,但这样缓存及时清理成了一个问题,所以需要ngx_cache_purge这个模块来在过期时间未到之前,手动清理缓存。
proxy模块中常用的指令是proxy_pass和proxy_cache。
nginx的web缓存功能主要是由proxy_cache、fastcgi_cache指令集和相关指令集完成,proxy_cache指令负责反向代理缓存后端服务器的静态内容,fastcgi_cache主要用来处理FastCGI动态进程缓存。
http {
#$upstream_cache_status #记录缓存命中率
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'"$upstream_cache_status"';
access_log logs/access.log main;
proxy_buffering on; #代理的时候,开启或关闭缓冲后端服务器的响应
proxy_temp_path /usr/local/nginx1.10/proxy_temp;
proxy_cache_path /usr/local/nginx1.10/proxy_cache levels=1:2 keys_zone=my-cache:100m inactive=600m max_size=2g;
server {
listen 80;
server_name localhost;
root html;
index index.php index.html index.htm;
#ngx_cache_purge #实现缓存清除
location ~/purge(/.*) {
allow 127.0.0.1;
allow 192.168.229.0/24;
deny all;
proxy_cache_purge my-cache $host$1$is_args$args;
}
location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
proxy_pass http://backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_cache my-cache;
add_header Nginx-Cache $upstream_cache_status;
proxy_cache_valid 200 304 301 302 8h;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1d;
proxy_cache_key $host$uri$is_args$args;
expires 30d;
}
相关选项说明
proxy_buffering on:代理时,开启或关闭缓冲后端服务器的响应。
当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入缓冲区中。
proxy_temp_path:缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被rename一下当做缓存放在proxy_cache_path。
0.8.9版本以后允许temp和cache两个目录在不同文件系统上(分区),然而为了减少性能损失还是建议把它们设成一个文件系统上。
proxy_cache_path:设置缓存目录,目录里的文件名是cache_key的MD5值。levels=1:2 keys_zone=my-cache:50m表示采用2级目录结构,第一层目录只有一个字符,是由levels=1:2设置,总共二层目录,子目录名字由二个字符组成。
Web缓存区名称为my-cache,内存缓存空间大小为100MB,这个缓冲zone可以被多次使用。文件系统上看到的缓存文件名类似于/usr/local/nginx1.10/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c。
inactive=600 max_size=2g表示600分钟没有被访问的内容自动清除,硬盘最大缓存空间为2GB,超过这个将清除最近最少使用的数据。
proxy_cache:引用前面定义的缓存区my-cache。
proxy_cache_key:定义如何生成缓存的键,设置web缓存的key值,nginx根据key值md5-hash存储缓存。
proxy_cache_valid:为不同的响应状态码设置不同的缓存时间,比如200、302等正常结果可以缓存的时间长点,而404、500等缓存时间设置短一些,时间到了文件就会过期,而不论是否刚被访问过。
add_header指令来设置response header,语法:add_header name value;
$upstream_cache_status这个变量来显示缓存的状态,可以在配置中添加一个http头来显示这一状态,
$upstream_cache_status包含以下几种状态:
·MISS 未命中,请求被传送到后端;
·HIT 缓存命中;
·EXPIRED 缓存已经过期请求被传送到后端;
·UPDATING 正在更新缓存,将使用旧的应答;
·STALE 后端将得到过期的应答;
expires:在响应头里设置Expires:或Cache-Control:max-age,返回给客户端的浏览器缓存失效时间。
9.nginx.conf配置实例
实现nginx在前端做反向代理服务器的完整配置文件,处理js、png等静态文件,jsp/php等动态请求转发到其它服务器tomcat/apache。
user www www;
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
worker_rlimit_nofile 10240;
pid logs/nginx.pid;
events {
use epoll; #位于event部分,epoll事件模型,提高nginx效率。
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"'
'"$upstream_cache_status"'; #记录缓存命中率。
access_log logs/access.log main;
server_tokens off; #关闭服务标识。
sendfile on; #开启高效文件传输模式。
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#Compression Settings #位于http部分,压缩设置。
gzip on;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_proxied any;
gzip_min_length 1k;
gzip_buffers 16 8k;
gzip_types text/plain text/css text/javascript application/json application/javascript
application/x-javascript application/xml;
gzip_vary on;
#end gzip
#http_proxy Settings #位于http部分,缓存设置。
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 75;
proxy_send_timeout 75;
proxy_read_timeout 75;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_buffering on; #代理的时候,开启或关闭缓冲后端服务器的响应。
proxy_temp_path /usr/local/nginx/proxy_temp;
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2 keys_zone=my-cache:100m
max_size=1000m inactive=600m max_size=2g;
#load balance Settings #负载均衡设置,转发到哪个web服务器。
upstream backend {
sticky;
server 192.168.229.140:80 weight=1 max_fails=2 fail_timeout=10s;
server 192.168.229.141:80 weight=1 max_fails=2 fail_timeout=10s;
}
#virtual host Settings
server {
listen 80;
server_name localhost;
charset utf-8;
location ~/purge(/.*) {
allow 127.0.0.1;
allow 192.168.229.0/24;
deny all;
proxy_cache_purge my-cache $host$1$is_args$args; #清除缓存
}
location / {
index index.php index.html index.htm;
proxy_pass http://backend; #位于server部分的location位置,代理路径。找寻真实IP地址。
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
proxy_pass http://backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_cache my-cache; #代理缓存
add_header Nginx-Cache $upstream_cache_status;
proxy_cache_valid 200 304 301 302 8h;
proxy_cache_valid 404 1m;
proxy_cache_valid any 1d;
proxy_cache_key $host$uri$is_args$args;
expires 30d;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.31.0/24;
deny all;
}
}
}
五、各种配置选项说明
1.main全局配置
woker_processes 4
在配置文件的顶级main部分,worker角色的工作进程个数,master进程是接收并分配请求给worker处理。
这个数值简单一点可以设置为cpu的核数grep ^processor/proc/cpuinfo | wc -l,也是auto值,如果开启了ssl和gzip更应该设置成与逻辑CPU数量一样甚至为2倍,可以减少I/O操作。
如果nginx服务器还有其它服务,可以考虑适当减少。
worker_cpu_affinity
也是写在main部分。在高并发情况下,通过设置cpu粘性来降低由于多CPU核切换造成的寄存器等现场重建带来的性能损耗。
例如:
(1)2核CPU,开启2个进程
worker_processes 2;
worker_cpu_affinity 01 10;
(2)2核CPU,开启4进程
worker_processes 4;
worker_cpu_affinity 01 10 01 10;
(3)2核CPU,开启8进程
worker_processes 8;
worker_cpu_affinity 01 10 01 10 01 10 01 10;
(4)8核CPU,开启2进程
worker_processes 2;
worker_cpu_affinity 10101010 01010101;
说明:10101010表示开启了第2,4,6,8内核,01010101表示开始了1,3,5,7内核。
worker_connections 4096
写在events部分。每一个worker进程能并发处理(发起)的最大连接数(包含与客户端或后端被代理服务器间等所有连接数)。
worker_rlimit_nofile 10240
写在main部分。worker进程的最大打开文件数限制。默认是没有设置,如果没设置的话,这个值为操作系统的限制(ulimit -n)。
可以限制为操作系统最大的限制65535。把这个值设高,这样nginx就不会有“too many open files”问题了。
use epoll
写在events部分。在Linux操作系统下,nginx默认使用epoll事件模型,得益于此nginx在Linux操作系统下效率相当高。
同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。
2.http服务器
与提供http服务相关的一些配置参数。例如:是否使用keepalive,是否使用gzip进行压缩等。
sendfile on
开启高效文件传输模式。
keepalive_timeout 65: 长连接超时时间,单位是秒,长连接请求大量小文件时,可以减少重建连接的开销,如果设置时间过长,用户又多,长时间保持连接会占用大量资源。
client_max_body_size 10m
允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值。
client_body_buffer_size 128k
缓冲区代理缓冲用户端请求的最大字节数
server_tokens off;
隐藏nginx的版本号
3.模块http_proxy
实现的是nginx作为反向代理服务器的功能,包括缓存功能
proxy_connect_timeout 60
nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 60
定义从后端服务器读取响应的超时。此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。
定义向后端服务器传输请求的超时。此超时是指相邻两次写操作之间的最长时间间隔,而不是整个请求传输完成的最长时间。如果后端服务器在超时时间段内没有接收到任何数据,接将被关闭。
proxy_buffer_size 4k
设置缓冲区的大小为size。nginx从被代理的服务器读取响应时,使用该缓冲区保存响应的开始部分。这部分通常包含着一个小小的响应头。该缓冲区大小默认等于proxy_buffers指令设置的一块缓冲区的大小,但它也可以被设置得更小。
proxy_buffers 8 4k
语法:proxy_buffers the_number is_size;
为每个连接设置缓冲区的数量为number,每块缓冲区的大小为size。这些缓冲区用于保存从被代理的服务器读取的响应。每块缓冲区默认等于一个内存页的大小。这个值是4K还是8K,取决于平台。
附:查看Linux内存页大小
[root@nginx ~]# getconf PAGESIZE
4096
[root@nginx ~]# getconf PAGE_SIZE
4096
proxy_busy_buffers_size 64k
高负荷下缓冲大小(默认大小是proxy_buffers指令设置单块缓冲大小的2倍)
proxy_max_temp_file_size
当proxy_buffers放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M。
proxy_temp_file_write_size 64k
当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。
4.模块http_gzip
gzip on:开启gzip压缩输出,减少网络传输。
gzip_min_length 1k:设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。建议设置成大于1k的字节数,小于1k可能会越压越大。
gzip_buffers 4 16k:设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,按照原始数据大小以16k为单位的4倍申请内存。如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。
gzip_http_version 1.1:用于识别http协议的版本,早期的浏览器不支持Gzip压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了Nginx的反向代理并期望也启用Gzip压缩的话,由于末端通信是http/1.1,故请设置为1.1。
gzip_comp_level 6:gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
gzip_types:匹配mime类型进行压缩,无论是否指定”text/html”类型总是会被压缩的。
默认值:gzip_types text/html (默认不对js/css文件进行压缩)
#压缩类型,匹配MIME类型进行压缩
#不能用通配符text/*
#(无论是否指定)text/html默认已经压缩
#设置哪种压缩文本文件可参考conf/mime.types
gzip_proxied any:Nginx作为反向代理的时候启用,根据某些请求和应答来决定是否在对代理请求的应答启用gzip压缩,是否压缩取决于请求头中的“Via”字段,指令中可以同时指定多个不同的参数,意义如下:
off – 关闭所有的代理结果数据的压缩
expired – 启用压缩,如果header头中包含“Expires”头信息
no-cache – 启用压缩,如果header头中包含“Cache-Control:no-cache”头信息
no-store – 启用压缩,如果header头中包含“Cache-Control:no-store”头信息
private – 启用压缩,如果header头中包含“Cache-Control:private”头信息
no_last_modified – 启用压缩,如果header头中不包含“Last-Modified”头信息
no_etag – 启用压缩 ,如果header头中不包含“ETag”头信息
auth – 启用压缩 , 如果header头中包含“Authorization”头信息
any – 无条件启用压缩
gzip_vary on:和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断是否需要压缩
5.模块http_stream
这个模块通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡,upstream后接负载均衡器的名字,后端realserver以host:port options;方式组织在{}中。
如果后端被代理的只有一台,也可以直接写在proxy_pass。
6.Location
root /var/www/html
定义服务器的默认网站根目录位置。如果locationURL匹配的是子目录或文件,root没什么作用,一般放在server指令里面或/下。
index index.jsp index.html index.htm
定义路径下默认访问的文件名,一般跟着root放
proxy_pass http:/backend
请求转向backend定义的服务器列表,即反向代理,对应upstream负载均衡器。也可以
proxy_pass http://ip:port。
proxy_redirect off;
指定是否修改被代理服务器返回的响应头中的location头域跟refresh头域数值
例如:
设置后端服务器“Location”响应头和“Refresh”响应头的替换文本。 假设后端服务器返回的响应头是“Location: http://localhost:8000/two/some/uri/”,那么指令proxy_redirect http://localhost:8000/two/ http://frontend/one/;将把字符串改写为 “Location:http://frontend/one/some/uri/”。
proxy_set_header Host $host;
允许重新定义或者添加发往后端服务器的请求头。
Host的含义是表明请求的主机名,nginx反向代理服务器会向后端真实服务器发送请求,并且请求头中的host字段重写为proxy_pass指令设置的服务器。
因为nginx作为反向代理使用,而如果后端真实的服务器设置有类似防盗链或者根据http请求头中的host字段来进行路由或判断功能的话,如果反向代理层的nginx不重写请求头中的host字段,将会导致请求失败。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
X_Forward_For字段表示该条http请求是由谁发起的?如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来自反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。因此,在配置用作反向代理的nginx中一般会增加两条配置,修改http的请求头:
proxy_set_header Host $host;
proxy_set_header X-Forward-For $remote_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
增加故障转移,如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
proxy_set_header X-Real-IP $remote_addr;
web服务器端获得用户的真实ip但是,实际上要获得用户的真实ip,也可以通过X-Forward-For。
7.验证nginx反向代理的缓存功能、负载均衡及健康检查
(1)下面我们来测试一下缓存功能
如果在缓存时间之内需要更新被缓存的静态文件怎么办,这时就需要手动来清除缓存。
ngx_cache_pure清除缓存模块使用说明
用谷歌浏览器测试时,可以按F12调用开发工具,选择Network选项,可以看到Response Headers,在这里可以看到请求的是否是缓存。
从图中可以看到,访问的服务器是192.168.31.83,缓存命中。
也可以查看缓存目录或nginx的访问日志。
(2)清除缓存
上述配置的proxy_cache_purge指令用于方便的清除缓存,但必须安装第三方的ngx_cache_purge模块才能使用。
使用ngx_cache_purge模块清除缓存(直接删除缓存目录下的文件也算一种办法):
GET方式请求URL
即使用配置文件中的location ~ /purge(/.*)
浏览器访问http://192.168.31.83/purge/your/may/path来清除缓存
缓存清除成功。
备注
(1)purge是ngx_cache_pure模块指令;
(2)your/may/path是要清除的缓存文件URL路径;
(3)若只有一台客户端要验证负载均衡和健康检查,可以先关掉缓存功能和保持session会话。
#proxy_buffering off;
#sticky
8.扩展:nginx修改版本等信息
(1)
[root@nginx ~]# vim /usr/local/src/nginx-1.0.12/src/core/nginx.h #编译前编辑
#define nginx_version
#define NGINX_VERSION
#define NGINX_VER
#define NGINX_VAR
修改上面的信息,即可更改nginx显示版本。
(2)
[root@nginx ~]# vim /usr/local/src/nginx-1.0.12/src/http/ngx_http_special_response.c #编译前编辑
static u_char ngx_http_error_full_tail[] =
static u_char ngx_http_error_tail[] =
修改上面的信息为你自己的。
(3)
[root@nginx ~]# vim /usr/local/src/nginx-1.0.12/src/http/ngx_http_header_filter_module.c #编译前编辑
static char ngx_http_server_string[]=
修改上面的信息为你自己的。
(4)编译完成之后,修改/usr/local/nginx/conf目录下面四个文件里面的版本名称。
[root@nginx ~]# vim /usr/local/nginx/conf
fastcgi.conf、fastcgi.conf.default、fastcgi_params、fastcgi_params.default
[root@nginx ~]# /usr/local/nginx/sbin/nginx -V #查看 nginx 版本号