nginx 反向代理时,如果后端有多台服务器,就可以实现负载均衡。
实现原理:把多台服务器用 upstream 绑定在一起并起一个组名,然后 proxy_pass 指向该组。
ngx_http_upstream_module 官方文档地址:
upstream 的上下文是 http
实现过程
例,有两台后端服务器,专门用来存放图片信息
① 编辑 /usr/local/nginx/conf/nginx.conf,添加两个 server 段,分别监听 81 端口 和 82 端口,都指向 /usr/local/nginx/html 目录:
[root@localhost nginx]# vim conf/nginx.conf
nginx.conf 添加:
server { listen 81; server_name localhost; root html; access_log logs/81-access.log main; } server { listen 82; server_name localhost; root html; access_log logs/82-access.log main; }
注:为了方便观察日志,两个 server 单独设置 access.log 目录。
保存退出。平滑重启 nginx。
此时访问 http://192.168.254.100:81/nginx.png 和 http://192.168.254.100:82/nginx.png:
② 在 http 段中添加一段 上游服务器,命名为 imageserver:
upstream imageserver{ server 192.168.254.100:81 weight=1 max_fails=2 fail_timeout=3; server 192.168.254.100:82 weight=1 max_fails=2 fail_timeout=3; }
注:
weight = 1 表示权重为 1
max_fails = 2 表示 最多 2 次连续连不上服务器就不再进行连接
fail_timeout = 3 表示 3 秒连不上服务器就算失效
③ 把之前配置的 location ~ image 注释:
location ~ image { # root /var/www/; # expires 1d; # index index.html; }
把之前配置的 location ~* \.(jpg|jpeg|png|gif) 中的缓存注释
location ~* \.(jpg|jpeg|png|gif){ expires 1d; }
④ 在 location ~* \.(jpg|jpeg|png|gif) 段中进行配置,如果遇到图片,则转发给 imageserver:
location ~* \.(jpg|jpeg|png|gif){ #expires 1d; proxy_pass http://imageserver; }
保存退出。平滑重启 nginx。
⑤ 再次访问 http://192.168.254.100/ecshop/index.php,观察访问日志:
81-access.log:
82-access.log:
⑥ 清空 81-access.log 和 82-access.log
[root@localhost nginx]# echo > logs/81-access.log [root@localhost nginx]# echo > logs/82-access.log
单独访问 ecshop 下某张图片,例如 http://192.168.254.100/ecshop/themes/default/images/logo.gif
81-access.log:
82-access.log 为空:
再次强刷该图片页面 http://192.168.254.100/ecshop/themes/default/images/logo.gif
再次查看两个日志文件:
可以多次测试,查看日志。
负载均衡的算法是针对后端服务器的顺序逐个请求。也有其他负载均衡的算法(例如使用第三方模块 ngx_http_upstream_consistent_hash)。
⑦ 观察本机 ip:192.168.254.1
再观察 access.log
访客的 ip 是 192.168.254.1,没有问题。
再观察负载均衡的日志:
访客的 ip 变成了前端服务器的 ip 地址,而不是真实的访客地址。
解决方案:
在 nginx.conf 的 location 段中,加入 X-Forwarder-For 信息:
location ~* \.(jpg|jpeg|png|gif){ proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://imageserver; }
此时再次刷新 ecshop,查看负载均衡日志:
http 头信息中就有了访客的真实 ip。