Nginx-tcp
Nginx TCP AND UDP LOAD BALANCER
前言
Nginx从Nginx Plus(商业授权版) 1.7.7 开始支持 TCP和UDP的负载均衡;Nginx开源版本从1.9.0起开始支持TCP的负载均衡,从1.9.13版本开始支持UDP和UNIX-domain sockets。
Nginx开源版本默认没有开启TCP负载均衡,开启需要在编译构建的时候新增–with-stream 参数,而Nginx Plus则默认就已经开启不需要额外参数。
下面是几个简单的Nginx配置(Example Configuration)
TCP
server { listen 127.0.0.1:12345; proxy_pass 127.0.0.1:8080; } server { listen 12345; proxy_connect_timeout 1s; proxy_timeout 1m; proxy_pass example.com:12345; }
UDP
server { listen 53 udp; proxy_responses 1; proxy_timeout 20s; proxy_pass dns.example.com:53; }
UNIX-domain sockets
server { listen [::1]:12345; proxy_pass unix:/tmp/stream.socket; }
Nginx TCP负载均衡算法
与Nginx http负载均衡一样,Nginx TCP负载均衡也支持如下负载均衡算法:
Round Robin: 对所有的backend轮询发送请求,算是最简单的方式了,也是默认的分配方式;例如:
upstream stream_backend { server backend1.example.com:12345; server backend2.example.com:12345; server backend3.example.com:12346; ... }
Least Connections(least_conn): 跟踪和backend当前的活跃连接数目,最少的连接数目说明这个backend负载最轻,将请求分配给他,这种方式会考虑到配置中给每个upstream分配的weight权重信息;例如:
upstream dns_servers { least_conn; server 192.168.136.130:53; server 192.168.136.131:53; ... }
Least Time(least_time): 请求会分配给响应最快和活跃连接数最少的backend;(该算法目前仅在Nginx Plus上支持);例如:
upstream stream_backend { least_time first_byte; server backend1.example.com:12345; server backend2.example.com:12345; server backend3.example.com:12346; }
Hash(hash key): client-server基于hash key计算hash值后,根据得到的hash值通过某种映射分配到backend。key值可以包括text, variables。例如:
upstream stream_backend { hash $remote_addr; server backend1.example.com:12345; server backend2.example.com:12345; server backend3.example.com:12346; }
Nginx TCP健康检查
开源版本的Nginx软件可以对上游服务器(upstream servers)的响应执行基本检查,尽可能重试失败的请求(也称为Passive Health Checks)。 NGINX Plus则额外增加了对外部应用程序运行状况检查(也称为Active Health Checks)和检查缓慢启动功能(slow‑start),可以对负载平衡组中新增和恢复的服务器正常添加。
Passive Health Checks:
Passive Health Checks (被动健康检查)意味着NGINX或NGINX Plus会监控服务通信是否可用,如果不可用,NGINX将尝试恢复。如果仍然无法恢复,NGINX会考虑该服务不可用,并暂时停止向该服务器发送请求,直到被再次被视为活动。
Nginx和Nginx Plus都支持下面指令,来判断服务是否不可用:
- fail_timeout - 设置考虑服务器不可用的多次失败尝试的时间,以及服务器不可用的时间(默认为10秒)。
- max_fails - 在fail_timeout时间内设置失败尝试次数,以考虑服务器不可用(默认为1连接)尝试。
例1
该示例显示,如果NGINX无法向某个服务器发送请求或至少三次未收到此服务器的响应,则立即认为该服务器不可用30秒:
upstream backend {
server backend1.example.com;
server backend2.example.com max_fails=3 fail_timeout=30s;
}
例2
在该例显示,假设有7个连接,那么有5个连接将转到backend1.example.com:12345(因为权重为5,weight=5),剩下的连接到第二和第三个服务器。如果在与服务器通信期间发生错误,则连接将被传递到下一个服务器,依此类推,直到所有正在运行的服务器都将被尝试。 如果与所有服务器的通信失败,则连接将关闭。
upstream backend {
server backend1.example.com:12345 weight=5;
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend2;
server backend3.example.com:12345 resolve;
server backup1.example.com:12345 backup;
}
Active Health Checks
NGINX Plus可以通过使用health_check指令包含在位置块中来配置最简单的运行状况检查。,并检查响应。
例1
以下示例 - 向每个服务发送带自定义的TCP请求。 返回良好的200的服务器被认为是健康的; 否则它们被标记为失败。
stream {
...
upstream stream_backend {
zone upstream_backend 64k;
server backend1.example.com:12345;
}
match http {
send "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n";
expect ~* "200 OK";
}
server {
listen 12345;
health_check match=http;
proxy_pass stream_backend;
}
}
更多health-check参考资料
简单测试
都在一个机器上, Nginx监听30003端口,然后开两个窗口,用nc监听 7773,7774端口。思路如下:
/ nc -l 7773
telnet--> Nginx(30003) -->
\ nc -l 7774
使用nc监听端口
$ nc -l 7773
$ nc -l 7774
Nginx配置
stream {
upstream backend {
server 127.0.0.1:7773;
server 127.0.0.1:7774;
}
server {
listen 127.0.0.1:30003;
proxy_timeout 20s;
proxy_pass backend;
}
}
测试
$ telnet 127.0.0.1 30003
第一次访问会代理到 7773端口,第二次访问会到7774端口。
线上配置文件
stream {
upstream stream_backend {
least_conn;
server 127.0.0.1:8801 max_fails=2 fail_timeout=30s;
server 127.0.0.1:8802 max_fails=2 fail_timeout=30s;
server 127.0.0.1:8803 max_fails=2 fail_timeout=30s;
}
server {
listen 8800;
proxy_timeout 10m;
proxy_connect_timeout 60;
proxy_pass stream_backend;
}
}
PS: 如果upstream组中只有一个服务器,max_fails,fail_timeout和slow_start参数都将被忽略,并且这样的服务器将永远不会被视为不可用。
参考文档
官方文档 1: ngx_stream_proxy_module
nginx-database-load-balancer-mysql-or-mariadb-galera-cluster