- 前言
- 读者对象
- 如何阅读本书
- 勘误和支持
- 致谢
- 第 1 篇 高性能网站构建
- 第 1 章 深入理解 DNS 原理与部署 BIND
- 第 2 章 全面解析 CDN 技术与实战
- 第 3 章 负载均衡和高可用技术
- 第 4 章 配置及调优 LVS
- 第 5 章 使用 HAProxy 实现 4 层和 7 层代理
- 第 6 章 实践 Nginx 的反向代理和负载均衡
- 第 7 章 部署商业负载均衡设备 NetScaler
- 第 8 章 配置高性能网站
- 第 9 章 优化 MySQL 数据库
- 第 2 篇 服务器安全和监控
- 第 10 章 构建企业级虚拟专用网络
- 第 11 章 实施 Linux 系统安全策略与入侵检测
- 第 12 章 实践 Zabbix 自定义模板技术
- 第 13 章 服务器硬件监控
- 第 3 篇 网络分析技术
- 第 14 章 使用 tcpdump 与 Wireshark 解决疑难问题
- 第 15 章 分析与解决运营商劫持问题
- 第 16 章 深度实践 iptables
- 第 4 篇 运维自动化和游戏运维
- 第 17 章 使用 Kickstart 完成批量系统安装
- 第 18 章 利用 Perl 编程实施高效运维
- 第 19 章 精通 Ansible 实现运维自动化
- 第 20 章 掌握端游运维的技术要点
- 第 21 章 精通手游运维的架构体系
最佳实践 31:安装与优化
Nginx 的安装过程比较简单,参照如下命令:
# wget http://nginx.org/download/nginx-1.9.7.tar.gz # tar zxvf nginx-1.9.7.tar.gz # cd nginx-1.9.7 # yum -y install pcre pcre-devel # ./configure --prefix=/usr/local/nginx --with-pcre --with-http_stub_status_module --with-http_ssl_module # make # make install
其中:
- --with-pcre 在 Nginx 添加对正则表达式的支持。
- --with-http_stub_status_module 添加对状态页面的支持。
- --with-http_ssl_module 在 Nginx 添加对 https 站点的支持。
以下实践基于图 6-2 所示的架构图。
图 6-2 Nginx 反向代理架构图
配置 Nginx 代理后端两台服务器,配置文件 nginx.conf 内容如代码清单 6-1 所示。
代码清单 6-1 初始 Nginx 配置
user nobody; worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; error_log logs/error.log; pid logs/nginx.pid; events { use epoll; worker_connections 10000; } 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"'; sendfile on; tcp_nopush on; keepalive_timeout 60; gzip on; upstream www { server 10.1.6.21; server 10.1.6.44; } server { listen 80; server_name localhost; charset koi8-r; access_log logs/host.access.log main; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 3; proxy_send_timeout 3; proxy_read_timeout 3; proxy_buffer_size 256k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; proxy_temp_file_write_size 256k; proxy_next_upstream error timeout invalid_header http_500 http_503 http_404; proxy_max_temp_file_size 128m; proxy_pass http://www; } } }
Nginx 的核心配置参数
Nginx 的核心配置参数如下:
- worker_processes:配置多少个工作进程,设置为与服务器核心(core)数量相同。
- worker_cpu_affinity(重要优化项):将进程与 CPU 绑定,提高了 Cpu Cache 的命中率,从而减少内存访问损耗,提高程序的速度。
- sendfile:对于静态大文件,启用 sendfile 加速文件读取。
- tcp_nopush:在 Linux socket 上启用 TCP_CORK 选项,和 sendfile 合用,加速大文件读取。
以下是超时相关的设置。
- client_header_timeout:客户端必须在此指定的时间内把请求的 header 传输完成,请设置成 5s 或以下值。对于抵挡慢速攻击有作用。
- client_body_timeout:Nginx 2 次连续读取客户端请求体的超时时间,请设置成 5s 或以下值。
- keepalive_timeout:定义保活时间,一般建议是 60s。
- proxy_connect_timeout:Nginx 连接后端服务器的超时时间,请设置成 5s 或以下值。
- proxy_send_timeout:Nginx 2 次连续向后端服务器发送请求的超时时间,请设置成 5s 或以下值。
- proxy_read_timeout:Nginx 2 次连续读取后端服务器返回的超时时间,请设置成 5s 或以下值。
以上超时时间,对于大型繁忙网站是最重要的调优项目。
请参照业务实际需求按照推荐值进行微调。
Nginx 负载均衡算法
在 Nginx 中,反向代理的负载均衡算法有以下 3 种。
- 轮询:不同的后端服务器按照请求轮询访问。
- 最小连接数:下一个请求被转发到当前活动连接数最小的服务器。
- IP 哈希:基于客户端 IP 来哈希,定位到该客户端需要被调度到的后端服务器。
Nginx Proxy 协议的选择
Nginx 反向代理 HTTP 协议时,默认使用的是 HTTP 1.0 去后端服务器获取响应内容,再返回给客户端。
HTTP 1.0 和 HTTP 1.1 的一个重要区别是前者不支持 HTTP Keep-Alive。
以最佳实践 26 中的配置为例,使用 webbench( http://home.tiscali.cz:8080/~cz210552/webbench.html )进行压力测试时可以看到在 Web1 服务器上:
# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t", state[key]}' TIME_WAIT 23704 #注意 TIME_WAIT 值非常高 FIN_WAIT1 18 ESTABLISHED 18 # netstat -an |more Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:5666 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:8649 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 10.1.6.21:80 10.1.6.28:52200 SYN_RECV tcp 0 0 10.1.6.21:80 10.1.6.28:52201 SYN_RECV tcp 0 0 0.0.0.0:38422 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN tcp 0 0 10.1.6.21:80 10.1.6.28:53257 TIME_WAIT #TIME_WAIT 的情况
同时在 Nginx1 的服务器上,看到有如下的报错信息,显示 Nginx 连接后端服务器失败:
2015/12/08 11:24:34 [error] 20137#0: *3293812 upstream timed out (110: Connection timed out) while connecting to upstream, client: 10.1.6.38, server: localhost, request: "GET /index.html HTTP/1.0", upstream: "http://10.1.6.44:80/index.html", host: "10.1.6.28"
看一下 TIME_WAIT 状态的产生过程,如图 6-3 所示。
图 6-3 TIME_WAIT 状态演进图
由图 6-3 可以看出后端服务器主动关闭了连接,未使用 Keep-Alive。
后端服务器主动关闭连接的动作,是由 Nginx1 的特殊 HTTP Header 引起的(文件:Nginx_proxy_without_Keep-Alive.pcap,Frame 15),如图 6-4 所示。
图 6-4 HTTP 1.0 协议反向代理时 Nginx 的网络行为
如图 6-4 所示,Nginx1 在向后端服务器请求时使用了 HTTP 1.0 同时使用 HTTP Header 的 Connection:Close 通知后端服务器主动关闭连接。
后端服务器在处理完请求返回时(文件:Nginx_proxy_without_Keep-Alive.pcap,Frame 19),发送了如下的数据包(TCP 的 flag 设置为 FIN,在应用层设置为“Connection:Close”),如图 6-5 所示。
图 6-5 HTTP 1.0 协议反向代理时后端服务器的网络行为
这样会导致任何一个客户端的请求都在后端服务器上产生一个 TIME_WAIT 状态的连接。
对于以上问题,需要修改 Nginx 使用协议 HTTP 1.1 向后端发送请求,同时支持 Keep-Alive。
这里修改 Nginx 的配置,配置文件如代码清单 6-2 所示。
代码清单 6-2 修改后的 Nginx 配置
user nobody; worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 10000; } 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"'; sendfile on; tcp_nopush on; keepalive_timeout 60; gzip on; upstream www { keepalive 50; #必须配置,建议值 50-100。 server 10.1.6.21; server 10.1.6.44; } server { listen 80; server_name localhost; charset koi8-r; access_log logs/host.access.log main; location / { proxy_http_version 1.1; #后端配置支持 HTTP 1.1;必需。 proxy_set_header Connection ""; #后端配置支持 HTTP 1.1;必需。 proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 3; proxy_send_timeout 3; proxy_read_timeout 3; proxy_buffer_size 256k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; proxy_temp_file_write_size 256k; proxy_next_upstream error timeout invalid_header http_500 http_503 http_404; proxy_max_temp_file_size 128m; proxy_pass http://www; } } }
通过对比代码清单 6-1 和代码清单 6-2,可以看出,设置 Nginx 代理使用 HTTP 1.1 和 Keep-Alive 时,必须要增加 3 个参数:keepalive 50、proxy_http_version 1.1、proxy_set_header Connection""。
此时通过分析网络行为可以看到(文件:Nginx_proxy_with_Keep-Alive.pcap,Frame 91),配置后 Nginx 重用了后端连接,如图 6-6 所示。
图 6-6 HTTP 1.1 协议反向代理时 Nginx 的网络行为概况
Frame 91 和 Frame 448 使用了同一个连接,如图 6-7 和图 6-8 所示。
图 6-7 HTTP 1.1 协议反向代理时 Nginx 第一次请求时的源端口号
由图 6-8 对比图 6-7 可以知道,2 次使用了同一个 TCP 连接。
图 6-8 HTTP 1.1 协议反向代理时 Nginx 第一次请求时的源端口号
Nginx 中 ip_local_port_range 问题
Nginx 在向后端服务器发起代理请求时,以本地的 IP 作为源 IP、以本地的随机端口号作为源端口号,因此同样存在和第 5 章中 HAProxy 相同的 ip_local_port_range 问题。
具体修改配置的方法,请参考第 5 章中的相关内容。
Nginx 被代理的后端服务器获取客户端 IP
根据上一小节的叙述,在 Nginx 被代理的后端服务器上,使用 netstat 等命令可以看到,和后端服务器建立 TCP 连接的来源 IP 不是客户端的 IP,而是 Nginx 的 IP。因此在后端应用程序需要获取客户端实际来源 IP 地址时,需要使用 Header X-Forwarded-For。
具体代码,请参考第 5 章中的相关内容。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论