深度优化Nginx(一)
通过博文Nginx初步优化就已经了解了Nginx的基础概念,已经可以对Nginx进行初步的优化了,包括:Nginx平滑升级
、更改Nginx版本信息、Nginx虚拟主机配置、nginx配置文件中location选项的作用等等。本篇博文主要针对Nginx进行进一步的优化。
博文大纲:
一、Nginx配置反向代理
二、Nginx的proxy缓存使用
三、优化Nginx服务的压缩功能
一、Nginx配置反向代理
配置Nginx作为反向代理和负载均衡,同时利用其缓存功能,将静态页面在Nginx中缓存,以达到降低后端服务器连接数的目的并检查后端web服务器的检查状态。
如图:
环境需求:
一台Nginx服务器(Centos系统)IP地址:192.168.1.1;
两台httpd服务器(Centos系统)IP地址:192.168.1.2 192.168.1.3;
下载Nginx软件包
安装Nginx:
[root@localhost ~]# yum -y install gcc gcc-c++ make libtool zlib zlib-devel pcre pcre-devel openssl openssl-devel//如果安装系统时,是最小化安装,则需要安装以上依赖包[root@localhost ~]# yum -y install pcre-devel zlib-devel openssl-devel //如果系统不是最小安装,则安装以上几个依赖包即可[root@localhost ~]# unzip nginx-sticky-module.zip -d /usr/src///使用 nginx-sticky-module 扩展模块实现 Cookie 会话黏贴(保持会话)[root@localhost ~]# tar zxf ngx_brotli.tar.gz -C /usr/src/[root@localhost ~]# tar zxf ngx_cache_purge-2.3.tar.gz -C /usr/src///使用 ngx_cache_purge 实现更强大的缓存清除功能//安装Nginx源码依赖包[root@localhost ~]# tar zxf nginx-1.14.0.tar.gz -C /usr/src/[root@localhost ~]# cd /usr/src/nginx-1.14.0/[root@localhost nginx-1.14.0]# ./configure --prefix=/usr/local/nginx --user=nginx \ --group=nginx --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=/usr/src/ngx_cache_purge-2.3/ --with-http_flv_module \ --add-module=/usr/src/nginx-sticky-module/ && make && make install
配置选项含义:
- --prefix=/usr/local/nginx:指定Nginx存放路径;
- --with-http_stub_status_module:通过网页方式监控nginx状态;
- --with-http_realip_module:显示客户端真是IP;
- --with-http_ssl_module:开启Nginx的加密传输功能;
- --with-http_gzip_static_module:开启Nginx扩展压缩模块;
- --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=/usr/src/ngx_cache_purge-2.3: 添加第三方模块,并指定第三方模块路径,支持缓存;
- --with-http_flv_module:支持flv视频流;
- --add-module=/usr/src/nginx-sticky-module: 添加第三方模块,并指定第三方模块路径,添加第三方模块格式:--add-module=源码解压后的路径;
[root@localhost ~]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ //创建符号链接[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf //编写Nginx主配置文件 ………… //省略部分内容http { include mime.types; default_type application/octet-stream; upstream lzj { //定义服务器群组,名称为lzj sticky; //session会话保持 server 192.168.1.2:80 weight=1 max_fails=2 fail_timeout=10s; server 192.168.1.3:80 weight=1 max_fails=2 fail_timeout=10s; } //定义了后台两台服务器,权重分别为1,最大失败次数为2,最大超时时间为10S location / { proxy_pass http://lzj; } //将原本的location规则注释,并重新定义转发到定义的lzj[root@localhost ~]# nginx -t //检测配置文件nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: [emerg] getpwnam("nginx") failednginx: configuration file /usr/local/nginx/conf/nginx.conf test failed[root@localhost ~]# useradd -s /sbin/nologin -M nginx //创建Nginx用户,并不允许登录操作系统[root@localhost ~]# nginx -t //检测配置文件nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: [emerg] mkdir() "/var/tmp/nginx/client" failed (2: No such file or directory)nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed[root@localhost ~]# mkdir -p /var/tmp/nginx/client //创建目录,用于存放客户端访问数据临时存放路径[root@localhost ~]# nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful//表示配置文件没有问题[root@localhost ~]# nginx //启动Nginx[root@localhost ~]# nginx -V //可以查看编译时,使用的配置参数nginx version: nginx/1.14.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --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=/usr/src/ngx_cache_purge-2.3/ --with-http_flv_module --add-module=/usr/src/nginx-sticky-module/
测试机操作如下:
第一台:
[root@localhost ~]# yum -y install httpd[root@localhost ~]# echo "192.168.1.2" > /var/www/html/index.html[root@localhost ~]# systemctl start httpd
第二台:
[root@localhost ~]# yum -y install httpd[root@localhost ~]# echo "192.168.1.3" > /var/www/html/index.html[root@localhost ~]# systemctl start httpd
Nginx测试效果:
[root@localhost ~]# curl 127.0.0.1192.168.1.2[root@localhost ~]# curl 127.0.0.1192.168.1.3
注意:如果需要在已经安装好的Nginx服务器上添加第三方模块,依然需要重新编译,但为了不覆盖原本的配置信息,请不要执行make install,而是直接复制可执行文件即可!
添加Nginx为系统服务脚本:
[root@localhost ~]# vim /etc/init.d/nginx #!/bin/bash# chkconfig: 2345 99 20# description: Nginx Service Control ScriptPROG="/usr/local/nginx1.10/sbin/nginx"PIDF="/usr/local/nginx1.10/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@localhost ~]# chmod +x /etc/init.d/nginx [root@localhost ~]# chkconfig --add nginx[root@localhost ~]# systemctl restart nginx
二、Nginx的proxy缓存使用
缓存也就是将一些静态文件从后端服务器缓存到nginx指定的缓存目录下,既可以减轻后端服务器负担,也可以加快访问速度,但这样缓存及时清理就成了一个头疼的问题。所以需要第三方模块ngx_cache_purge来在过期时间未到之前,手动清理缓存。
proxy模块常用的指令是proxy_pass和proxy_cache
nginx的web缓存功能只要就是由proxy_cache、fastcgi_cache指令集和相关指令集完成:
- proxy_cache:负责反向代理缓存后端服务器的静态内容;
- fastcgi_cache:主要用来处理fastcgi动态进程缓存;
为了使nginx能够拥有缓存功能,需要修改其配置文件,如下:
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf………… //省略部分内容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/nginx/proxy_temp; //定义缓存临时目录 proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2 keys_zone=my-cache:100m inactive=600m max_size=2g;//定义缓存目录,具体信息已在配置文件外部进行说明………… //省略部分内容 location ~/purge(/.*) { //定义缓存清除策略 allow 127.0.0.1; allow 192.168.1.0/24; deny all; proxy_cache_purge my-cache $host$1$is_args$args; } location / { proxy_pass http://lzj; //请求转向lzj定义的服务器列表 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-Real-IP $remote_addr; //web 服务器端获得用户的真实 ip 但是,实际上要获得用户的真实 ip,也可以通过下面的X-Forward-For proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #后端的 Web服务器可以通过 X-Forwarded-For 获取用户真实 IP,X_Forward_For 字段#表示该条 http 请求是有谁发起的?如果反向代理服务器不重写该请求头的话,那么后端#真实服务器在处理时会认为所有的请求都来自反向代理服务器,如果后端有防护策略#的话,那么机器就被封掉了。因此,在配置用作反向代理的 nginx 中一般会增加两条配置,以便修改 http 的请求头部 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; #增加故障转移,如果后端的服务器返回 502、504、执行超时等错误,#自动将请求转发到upstream 负载均衡池中的另一台服务器,实现故障转移。 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; }[root@localhost ~]# nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful//检测配置文件没有问题[root@localhost ~]# nginx -s reload //重新加载nginx配置文件
配置选项详解:
- levels=1:2 keys_zone=my-cache:100m 表示采用 2 级目录结构,第一层目录只有一个字符,是由 levels=1:2 设置,总共二层目录,子目录名字由二个字符组成。Web 缓存区名称为 my-cache,内存缓存空间大小为 100MB,这个缓冲 zone 可以被多次使用;
- inactive=600 max_size=2g 表示 600 分钟没有被访问的内容自动清除,硬盘最大缓存空间为2GB,超过这个大学将清除最近最少使用的数据;
- proxy_cache : 引用前面定义的缓存区 my-cache;
- proxy_cache_key :定义如何生成缓存的键,设置 web 缓存的 key 值,nginx 根据 key 值 md5哈希存储缓存;
- 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,返回给客户端的浏览器缓存失效时间;
客户端浏览器访问:
使用F5刷新页面之后,出现如下页面:
清除缓存访问以下路径,如图:
如果访问时访问的URL是:http:192.168.1.1/index.html,那么清除缓存则需要http:192.168.1.1/purge/index.html。
这些从nginx的访问日志中,也可以看出,如图:
注意:测试时,注意清除客户端浏览器的缓存!
三、优化Nginx服务的压缩功能
优化Nginx服务的压缩功能就需要进行以下操作:
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf……………… //省略部分内容http { include mime.types; default_type application/octet-stream; upstream lzj { sticky; server 192.168.1.2:80 weight=1 max_fails=2 fail_timeout=10s; server 192.168.1.3:80 weight=1 max_fails=2 fail_timeout=10s; } 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; brotli on; brotli_types text/plain text/css text/xml application/xml application/json; brotli_static off; //是否允许查找预处理好的、以 .br结尾的压缩文件,可选值为on、off、always。 brotli_comp_level 11; //压缩的级别,范围是"1~14",值越大,压缩比越高 brotli_buffers 16 8k; //读取缓冲区数量和大小 brotli_window 512k; //滑动窗口大小 brotli_min_length 20; //指定压缩数据的最小字节 server_tokens off; //隐藏版本信息 sendfile on; //开启高效文件传输 keepalive_timeout 65; //长连接超时时间,单位是秒 gzip on; //开启 gzip 压缩 gzip_comp_level 6; //压缩的级别,范围是"1~6",值越大,压缩比越高 gzip_http_version 1.1; //http版本为1.1 gzip_proxied any; // Nginx 作为反向代理的时候启用,根据某些请求和应答来决定是否在对代理请求的应答启用 gzip 压缩,是否压缩取决于请求头中的"Via"字段,指令中可以同时指定多个不同的参数,常用的参数如下:off - 关闭所有的代理结果数据的压缩;expired - 启用压缩,如果 header 头中包含 "Expires" 头信息;no-cache - 启用压缩,如果 header 头中包含 "Cache-# Control:no-cache" 头信息;private - 启用压缩,如果 header 头中包含 "Cache-Control:private" 头信息;no_last_modified - 启用压缩,如果 header 头中不包含 "Last-Modified" 头信息;no_etag - 启用压缩 ,如果 header 头中不包含 "ETag" 头信息;auth - 启用压缩 , 如果 header 头中包含 "Authorization" 头信息;any - 无条件启用压缩; gzip_min_length 1k; gzip_buffers 16 8k; gzip_types text/plain text/css text/xml application/xml application/json; gzip_vary on; client_max_body_size 10m; client_body_buffer_size 128k; //缓冲区代理缓冲用户端请求的最大字节数 proxy_connect_timeout 75; //nginx 跟后端服务器连接超时时间(代理连接超时) proxy_read_timeout 75; //定义从后端服务器读取响应的超时 proxy_buffer_size 4k; //设置缓冲区的大小为 size 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 inactive=600m max_size=2g; #sendfile on; #tcp_nopush on; #keepalive_timeout 0; #keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; charset utf-8;……………… //省略部分内容,在location规则最后添加 location /nginx_status { stub_status on; access_log off; allow 192.168.1.0/24; deny all; }[root@localhost ~]# nginx -tnginx: [emerg] unknown directive "brotli" in /usr/local/nginx/conf/nginx.conf:32nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed//检查配置文件发现brotli这个工具在编译时忘记安装了(故意的)
接下进行安装原本的模块:
[root@localhost ~]# cd /usr/src/nginx-1.14.0/ //进入源码包路径[root@localhost nginx-1.14.0]# nginx -V //-V查询编译安装时,使用的那些参数nginx version: nginx/1.14.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --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=/usr/src/ngx_cache_purge-2.3/ --with-http_flv_module --add-module=/usr/src/nginx-sticky-module/[root@localhost nginx-1.14.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --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=/usr/src/ngx_cache_purge-2.3/ --with-http_flv_module --add-module=/usr/src/nginx-sticky-module/ --add-module=/usr/src/ngx_brotli && make && make install//将上述查到的已加载的模块复制以下,重新编译以下,同时,加上需要添加的模块//比如我在上面添加了第三方模块"--add-module=/usr/src/ngx_brotli"[root@localhost ~]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak//将原本的命令进行备份[root@localhost ~]# cp /usr/src/nginx-1.14.0/objs/nginx /usr/local/nginx/sbin///复制新生成的nginx命令到指定的目录中[root@localhost ~]# ln -sf /usr/local/nginx/sbin/nginx /usr/local/sbin/ //对新命令做一个强制软连接[root@localhost ~]# nginx -s reload //重新加载nginx配置文件[root@localhost ~]# nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful//检查配置文件[root@localhost ~]# nginx -s stop[root@localhost ~]# nginx//重新启动nginx服务,注意清除浏览器本地的缓存信息
客户端验证访问:
鉴于复制的问题,最后附上本篇博文有关没有注释的完整的Nginx配置文件:
#user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; upstream lzj { sticky; server 192.168.1.2:80 weight=1 max_fails=2 fail_timeout=10s; server 192.168.1.3:80 weight=1 max_fails=2 fail_timeout=10s; } 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; brotli on; brotli_types text/plain text/css text/xml application/xml application/json; brotli_static off; brotli_comp_level 11; brotli_buffers 16 8k; brotli_window 512k; brotli_min_length 20; server_tokens off; sendfile on; keepalive_timeout 65; 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/xml application/xml application/json; gzip_vary on; 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 inactive=600m max_size=2g; #sendfile on; #tcp_nopush on; #keepalive_timeout 0; #keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; charset utf-8; #charset koi8-r; #access_log logs/host.access.log main; location ~/purge(/.*) { allow 127.0.0.1; allow 192.168.1.0/24; deny all; proxy_cache_purge my-cache $host$1$is_args$args; } location / { proxy_pass http://lzj; 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.1.0/24; deny all; }//以下的内容没有进行修改所以就不复制了
-------- 本文至此结束,感谢阅读 --------