使用 nginx 实现后端 HTTP 服务器的故障转移(failover)
一般情况下,nginx 的 upstream 通常的用途是实现负载均衡:
但是实际上,nginx 对 upstream 的多个设备可以设置不同的状态参数:
- weight 默认为1. weight越大,负载的权重就越大;
- max_fails : 允许请求失败的次数默认为1. 当超过最大次数时,返回proxy_next_upstream 模块定义的错误;
- fail_timeout: max_fails 次失败后,暂停的时间;
- down 表示当前的server暂时不参与负载;
- backup: 其它所有的非 backup 机器 down 或者忙的时候,请求 backup 机器(所以这台机器压力会最轻);
因此,upstream 同样可以用于配置 “故障转移”的服务器集群,一般用于这类场景:一般情况下优先使用服务器1,只有这台服务器出故障后才转移到其他的服务器(因为其他服务器性能、网络速度不如服务器1等原因),下面就是一个配置的例子:
worker_processes 1; events { worker_connections 1024; } http { default_type application/octet-stream; client_max_body_size 4m; keepalive_timeout 65; upstream backend_servers { server localhost:7001 max_fails=3 fail_timeout=30s; # 下面两行 "backup" 只有在上面 "7001" 服务器失败后才会被访问(此时两台服务器会采用同样的权重进行负载均衡) server localhost:7002 max_fails=3 fail_timeout=30s backup; server localhost:7003 max_fails=3 fail_timeout=30s backup; # 如果为上面两行 "backup" 设定悬殊的 "weight" 参数,可以控制 failover 的顺序(比如设置只有 "7002" 宕机后才会访问到 "7003") #server localhost:7002 max_fails=3 fail_timeout=30s backup weight=2000000000; #server localhost:7003 max_fails=3 fail_timeout=30s backup weight=1; } server { listen 8001; server_name example.com; location / { proxy_pass http://backend_servers; } } }
附件 test-http-server.py 和 nginx.conf 是用于测试的 Python HTTP 服务器和 nginx 配置:
- 首先依次通过如下命令启动 3 台后端 HTTP 服务器:
python test-http-server.py 7001 python test-http-server.py 7002 python test-http-server.py 7003
- 然后使用如下命令启动 nginx 服务器:
# 启动 nginx nginx -c `pwd`/nginx.conf # 停止 nginx nginx -c `pwd`/nginx.conf -s quit
- 通过浏览器访问类似这样的 URL: http://localhost:8001/TEST/001
- 正常结果应该是 localhost 7001;
- 如果停止相应的服务器,可以看到浏览器上的输出切换到后续其他服务器(输出 localhost 7002、localhost 7003)
nginx 反向代理功能介绍及在Windows下使用的Portable版本
想做一个公网访问内网的反向代理,但是在公网机器上的 Apache 怎么也安装不上(那个机器已经安装了两个 Apache,不知道是不是这方面的原因),于是就研究了一下如何使用 nginx 来实现反向代理。
搜索了一下资料,发现 nginx 似乎比 Apache 更好用,包括:
- 配置的方式类似 json,比较容易阅读;
- 运行简单,Windows 平台上的二进制文件本身就是解压即可运行,够 “Portable”;
- 在网上找到了使用 Windows Service Wrapper 将 nginx 转为一个 Windows 服务的方法,经试验简单有效,见 Nginx Windows Service。
nginx 自然在其 官网 上 下载,本文使用的是 Stable version, nginx/Windows-1.2.7;
winsw(Windows Service Wrapper)原来 host 在 https://kenai.com/,不过Oracle 收购 Sun 之后这个网站似乎受到一些影响,目前已经转到了 github 上: https://github.com/kohsuke/winsw/ (是用 C# 编写的,呵呵), 其二进制文件可以在 Nginx Windows Service 文中提到的地点 http://download.java.net/maven/2/com/sun/winsw/winsw/ 下载(似乎是一个 maven 的仓库?);
本文附件中的 “PortableNgnix” 只是简单的将解压后的 nginx Windows 程序和 winsw 合并在一起而已,其中包含一个简单的 proxy 写法示例(将 http://localhost/main/browser/AdminShells/ 反向代理连接到 http://thinkbase.net/main/browser/AdminShells/ ):
#user nobody; worker_processes 1; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location /main/browser/AdminShells/ { proxy_pass http://thinkbase.net/main/browser/AdminShells/; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
其实很多时候还有更简单的写法,比如下面这个反向代理 svn 服务器的例子:
#user nobody; worker_processes 1; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; keepalive_timeout 65; server { listen 81; server_name localhost; location / { proxy_pass http://192.168.0.77:8080/; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
使用 winsw 创建 Windows Service 的过程也很简单,附件 PortableNginx.7z 中的例子是假设 nginx 解压后在 D:\PortableNginx 目录下的情况:
<service> <id>nginx-reverse-proxy</id> <name>nginx reverse proxy</name> <description>nginx reverse proxy</description> <executable>D:\PortableNginx\nginx\nginx.exe</executable> <logpath>D:\PortableNginx\nginx\logs</logpath> <logmode>roll</logmode> <depend></depend> <startargument>-p D:\PortableNginx\nginx -c D:\PortableNginx\nginx\proxy.conf</startargument> <stopargument>-p D:\PortableNginx\nginx -s stop</stopargument> </service>
更多细节可以继续研究附件(参见其中的 readme.txt),或者把附件解压后自己体验,下面是 winsw 产生的 Windows Servicce 以及 Service 运行时产生的相关文件截图,供参考:
.