Nginx TCP和UDP负载均衡
Nginx TCP和UDP负载
负载均衡是指有效的通过多个后端服务器分发网络流量。
Nginx能代理和负载均衡TCP、UDP通信。TCP(传输控制协议)、UDP(用户数据包协议)是许多流行应用程序和服务的协议,例如LDAP、MySQL和RTMP使用TCP协议,DNS、syslog和RADIUS
2 需要使用--with-stream配置标记构建最新Nginx,或最新的Nginx+(不需要额外构建步骤)
应用程序、数据库或服务基于TCP或UDP通信
Upstream服务器运行相同的应用程序、数据库或服务实例
3 配置反向代理首先,你需要配置反向代理,因此,Nginx转发来自客户端的TCP连接或UDP数据包到upstream组或一个代理服务器。
打开Nginx配置文件并执行以下步骤:
创建顶级stream {}块
stream {
...
}
在顶级stream {}上下文中为每个虚拟主机定义一个或多个server {}配置块。
在每个server {}配置块中包括listen指令定义服务器监听的IP地址和/或端口。对于UDP通信,也包括udp参数。TCP是stream上下文的默认协议:
stream {
server {
listen 12345;
...
}
server {
listen 53 udp;
...
}
...
}
包括proxy_pass指令定义代理服务器或upstream组stream {
server {
listen 12345;
proxy_pass stream_backend;
}
server {
listen 12346;
proxy_pass backend.example.com:12346;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
...
}
可选,如果你的代理服务器多个网络接口,你能配置Nginx选择源IP地址连接到upstream服务器。代理服务器在Nginx后面配置为从特定IP网络或IP地址范围接收连接是有用的。指定proxy_bind指令和必要的网络接口的IP地址:
stream {
...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_bind 127.0.0.1:12345;
}
}
可选,你能调整两个内存缓存,Nginx能从客户端和upstream连接放入数据。如果有一个体积小的数据,减少缓存可以节约内存资源。如果有大量数据,增加缓存大小减少套接字读写操作次数。一旦在一个连接接收到数据,Nginx读取它并在其它连接转发。缓存使用proxy_buffer_size指令控制:stream {
...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_buffer_size 16k;
}
}
4 配置TCP和UDP负载均衡为了配置负载均衡:
1、创建服务器组,或upstream组将负载均衡通信。定义一个或多个upstream {}配置块在顶级steam {}上下文,设置upstream组的名字,例如,TCP服务器steam_backed和UDP服务器dns_servers:
stream {
upstream stream_backend {
...
}
upstream dns_servers {
...
}
...
}
2、在upstream组中填充upstream服务器。upstream {}块中,为每个upstream服务器添加server指令,指定IP地址或主机名(解析多个IP地址)和必须的端口号。
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
...
}
upstream dns_servers {
server 192.168.136.130:53;
server 192.168.136.131:53;
...
}
...
}
3、配置负载均衡方法
round-robin(轮询)——默认,Nginx使用轮询算法负载均衡通信。因为是默认方法,所以没有round-robin指令;只创建upstream配置块在顶级stream上下文并像之前步骤添加server指令。
last_conn(最少连接)——Nginx选择当前活跃连接数较少的服务器。
least_tome——Nginx选择最低平均延迟和最少活跃连接的服务器。最低活跃连接基于least_time指令的以下参数计算:
connect——连接upstream服务器的时间
first_byte——接收第一个数据字节的时间
last_byte——从服务器接收完整响应的时间
upstream stream_backend {
least_time first_byte;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
hash——Nginx基于用户定义键选择服务器,例如,源IP地址upstream stream_backend {
hash $remote_addr;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
hash负载均衡方法也用于配置回话持久化。哈希函数基于客户端IP地址,来自指定客户端的连接总是传递给相同的服务器,除非服务器宕机或不可用。指定一个可选的consistent参数应用ketama一致性哈希方法
hash $remote_addr consistent;
4、可选,指定最大连接数、服务器权重等
upstream stream_backend {
hash $remote_addr consistent;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
...
}
如果你通过主机名标识服务器,配置主机名解析多个IP地址,然后Nginx通过IP地址使用轮询算法负载均衡。在这种情况下,你必须在proxy_pass指令中指定服务器的端口号,不必指定协议:
stream {
...
server {
listen 12345;
proxy_pass backend.example.com:12345;
}
}
5 被动健康检查如果试图连接upstream服务器超时或出错,Nginx标记服务器为不可用并在指定时间内停止发送请求给该服务器。为了定义不可用条件,包括以下参数到server指令:
fail_timeout——同Nginx负载均衡章节
max_fails——同Nginx负载均衡章节
fail_timeout默认为10秒,max_fails默认为1次。因此,如果连接10秒内尝试至少一次失败,Nginx标记服务器10秒内不可用。
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12346 max_conns=3;
}
6 主动健康检查健康检查能配置测试广范围的错误类型。例如,Nginx能不断测试upstream服务器的响应能力并避免服务器故障。
6.1 工作原理Nginx发送特定健康检查请求到每个upstream服务器并检查响应满足某一条件。如果不能连接到服务器,那么健康检查失败,服务器不健康。Nginx不代理客户端连接到不健康的服务器。如果多个健康检查定义在服务器组中,相应服务器的任意一个检查不通过该服务器都是不健康的。
6.2 预备条件你在stream上下文中配置upstream服务器组
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
}
你配置一台服务器传递通信(在这种情况下,是TCP连接)到服务器组server {
listen 12345;
proxy_pass stream_backend;
}
6.3 基础配置指定共享内存区域
stream {
upstream stream_backend {
zone stream_backend 64k;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
}
启用健康检查server {
listen 12345;
proxy_pass stream_backend;
health_check;
health_check_timeout5s;
}
health_check指令启用健康检查功能,health_check_timeout覆盖健康检查的proxy_timeout。
为了启用健康检查UDP通信,为health_check指令指定udp参数:
server {
listen 5053;
proxy_pass dns_servers;
health_check udp;
health_check_timeout 5s;
}
6.4 健康检查调优默认,Nginx尝试每5秒连接upstream服务器组中的每台服务器。如果不能建立连接,Nginx认为健康检查失败,标记为不健康,停止转发客户端连接到服务器。
为了改变默认行为,包括参数到health_check指令:
interval——Nginx多久发送一次健康检查请求(默认5秒)
passes——服务器连续多少次响应健康检查认为是健康(默认是1次)
fails——服务器连续多少次健康检查失败认为是不健康(默认是1次)
server {
listen 12345;
proxy_pass stream_backend;
health_check interval=10 passes=2 fails=3;
}
在例子中,TCP健康检查时间间隔增加到10秒,服务器认为连续3次健康检查失败是不健康,服务器需要连续2次通过健康检查才再次认为是健康的。
默认,Nginx发送健康检查消息给upstream块中的server指令的特定端口。你能指定其它的健康检查端口,当许多服务在相同主机检查健康时非常有用。为了覆盖端口,指定health_check指令的port参数:
server {
listen 12345;
proxy_pass stream_backend;
health_check port=8080;
}
6.5 使用match配置块调优健康检查你能通过配置大量健康检查测试验证服务响应。这些测试放置在stream{}上下文中的match {}配置块。指定match {}块并设置它的名字,例如,tcp_test:
stream {
...
match tcp_test {
...
}
}
然后在health_check指令包括match参数和match块相同名称引用块:
stream {
server {
listen 12345;
health_check match=tcp_test;
proxy_pass stream_backend;
}
}
健康检查的条件或测试使用send和expect参数设置:
send——发送给服务器文本字符串或十六进制字符(“/x”后面跟两个十六进制数字) expect——服务器返回的数据匹配的字符串货正则表达式这些参数能用于不同的组合,但不能同时制定超过一个send和一个expect参数。参数配置也依赖于使用(TCP或UDP)的协议。
6.5.1 调优TCP健康检查为了调优TCP健康检查,你能组合send和expect参数:
如果没有send或expect参数指定,测试连接服务器能力。
如果expect参数被指定,服务器期望无条件发送数据:
match pop3 {
expect ~* "+OK";
}
如果send参数指定,它期望连接将成功建立并指定字符串发送给服务器:match pop_quit {
send QUIT;
}
如果send和expect参数被指定stream {
upstream stream_backend {
zone upstream_backend 64k;
server backend1.example.com:12345;
}
match http {
send "GET / HTTP/1.0rnHost: localhostrnrn";
expect ~* "200 OK";
}
server {
listen 12345;
health_check match=http;
proxy_pass stream_backend;
}
}
例子显示为了健康检查传入,HTTP请求必须发送到服务器,并期望服务器结果包含”200 OK”表示HTTP响应成功。
6.5.2 UDP健康检查调优为了调优UDP健康检查,你应该指定send和expect参数:
NTP例子
match ntp {
send xe3x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00;
expect ~* x24;
}
DNS例子match dns {
send x00x2ax00x00x00x01x00x00x00x00x00x00x03x73x74x6cx04x75x6dx73x6cx03x65x64x75x00x00x01x00x01;
expect ~* "health.is.good";
}
7 动态配置Upstream服务器组能容易使用简单的HTTP接口重新动态配置。使用该接口,你能浏览所有服务器在upstream组或特定服务器,修改服务器参数,并添加或删除upstream服务器。
为了启用动态配置:
创建顶级http {}块或确保在你的配置文件中存在
http {
...
}
创建配置请求的location,例如,upstream_conf。http {
server {
location /upstream_conf {
...
}
}
}
在该location中指定upstream_conf指令——一个能用于解释和重新配置upstream组的处理器http {
server {
location /upstream_conf {
upstream_conf;
...
}
}
}
限制该location的访问
http {
server {
location /upstream_conf {
upstream_conf;
allow 127.0.0.1;
deny all;
}
}
}
创建共享内存区域stream {
upstream stream_backend {
zone backend 64k;
...
}
}
7.1 动态配置例子stream {
...
upstream appservers {
zone appservers 64k;
server appserv1.example.com:12345 weight=5;
server appserv2.example.com:12345 fail_timeout=5s;
server backup1.example.com:12345 backup;
server backup2.example.com:12345 backup;
}
server {
proxy_pass appservers;
health_check;
}
}
http {
...
server {
location /upstream_conf {
upstream_conf;
allow 127.0.0.1;
deny all;
}
}
}
浏览所有备机http://127.0.0.1/upstream_conf?stream=&upstream=appservers&backup=
添加新服务器到服务器组http://127.0.0.1/upstream_conf?stream=&add=&upstream=appservers&server=appserv3.example.com:12345&weight=2&max_fails=3
从服务器组删除服务器http://127.0.0.1/upstream_conf?stream=&remove=&upstream=appservers&id=2
修改指定服务器http://127.0.0.1/upstream_conf?stream=&upstream=appservers&id=2&down=
8 TCP和UDP负载均衡配置例子stream {
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
server 192.168.136.132:53;
}
server {
listen 12345;
proxy_pass backend;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
server {
listen 12346;
proxy_pass backend.example.com:12346;
}
}