Nginx系列之3:反向代理和负载均衡
反向代理
最简单的配置 location /some/path/ { proxy_pass http://www.example.com/link/; }
完整的
upstream apachephp { server ip:8080; #Apache } server { listen 80; server_name www.redis.com.cn; access_log logs/redis.access.log main; error_log logs/redis.error.log; root html; index index.html index.htm index.php; ## send request back to apache ## location / { proxy_pass http://apachephp; #Proxy Settings 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_max_temp_file_size 0; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } }
nginx 为实现反向代理的需求增加了一个 ngx_http_proxy_module 模块。其中 proxy_set_header 指令就是该模块需要读取的配置。
现在对每句配置做个说明
-
proxy_set_header Host local.baidu.com;
HTTP header 中的 Host 含义为所请求的目的主机名。当 nginx 作为反向代理使用,而后端真实 web 服务器设置有类似 防盗链功能 ,或者根据 HTTP header 中的 Host 字段来进行 路由 或 过滤 功能的话,若作为反向代理的 nginx 不重写请求头中的 Host 字段,将会导致请求失败。 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
HTTP header 中的 X_Forward_For 表示该条 http 请求是由谁发起的。如果反向代理服务器不重写该请求头的话,那么后端真实 web 服务器在处理时会认为所有的请求都来自反向代理服务器。如果后端 web 服务器有防攻击策略的话,那么反向代理服务器对应的 ip 地址就会被封掉。
上述配置的意思是增加一个$proxy_add_x_forwarded_for
到X-Forwarded-For
里去,注意是增加,而不是覆盖。当然由于默认的X-Forwarded-For
值是空的,所以我们总感觉X-Forwarded-For
的值就等于$proxy_add_x_forwarded_for
的值。
X-Forwarded-For
的格式为X-Forwarded-For:real client ip, proxy ip 1, proxy ip N
,每经过一个反向代理就在请求头X-Forwarded-For后追加反向代理IP。 -
proxy_connect_timeout
nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
负载均衡
轮询
upstream OrdinaryPolling { server 127.0.0.1:8080; server 127.0.0.1:8081; } server { listen 80; server_name localhost; location / { proxy_pass http://OrdinaryPolling; index index.html index.htm index.jsp; } }
加权轮询
upstream OrdinaryPolling { server 127.0.0.1:8080 weight=5; server 127.0.0.1:8081 weight=2; } server { listen 80; server_name localhost; location / { proxy_pass http://OrdinaryPolling; index index.html index.htm index.jsp; } }
IP Hash
算法:根据客户端ip进行Hash得到一个数值,然后使用该数值对服务器个数取模,得到的结果就是映射的服务器序号
(在服务器个数不变的情况下)可保证同一ip地址的请求始终映射到同一台服务器,解决了session共享问题。
集群环境下的 session 共享问题,通常由两种方法:
1、第一种方法是选择一个中间件,将登录信息保存在一个中间件上,这个中间件可以为 Redis 这样的数据库。那么第一次登录,我们将session 信息保存在 Redis 中,跳转到第二个服务器时,我们可以先去Redis上查询是否有登录信息,如果有,就能直接进行登录之后的操作了,而不用进行重复登录。
2、第二种方法是根据客户端的IP地址划分,每次都将同一个 IP 地址发送的请求都分发到同一个 Tomcat 服务器,那么也不会存在 session 共享的问题。
而 nginx 的基于 IP 路由负载的机制就是上诉第二种形式。
upstream OrdinaryPolling { ip_hash; server 127.0.0.1:8080 weight=5; server 127.0.0.1:8081 weight=2; } server { listen 80; server_name localhost; location / { proxy_pass http://OrdinaryPolling; index index.html index.htm index.jsp; } }
uri Hash
(在服务器个数不变的情况下)可保证同一uri始终映射到同一台服务器
nginx在1.7.2之后支持uri_hash
upstream myserver { hash $request_uri; # with default weight for all (weight=1) server 192.168.250.220:8080; server 192.168.250.221:8080; server 192.168.250.222:8080; }
配置:
1)down
表示单前的server暂时不参与负载
2)Weight
默认为1.weight越大,负载的权重就越大。
3)max_fails
允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4)fail_timeout
max_fails 次失败后,暂停的时间。
5)Backup
其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
使用Nginx的高可用,除了要实现网站的高可用,也就是提供n多台服务器用于发布相同的服务,添加负载均衡服务器分发请求以保证在高并发下各台服务器能相对饱和的处理请求。同样,负载均衡服务器也需要高可用,以防如果负载均衡服务器挂掉了,后面的应用服务器也紊乱无法工作。
实现高可用的方案:添加冗余。
目前维护的开源产品:https://gitee.com/475660