Nginx Stream L4 负载均衡
需求
使用Nginx Stream实现反向代理(通信协议:TCP),并结合DNS、keepalived 和VIP ,实现Nginx Stream的多活和高可用。
实现与配置
Nginx Stream 安装
Nginx Stream 编译安装,参照本文 附录一 Nignx Stream 安装 注意: 在centos7 OS上通过yum安装的nginx-all-modules 已经包含Nginx Stream module,可以直接使用cenots/RHEL yum install nginx
Nginx Stream L4 负载基本配置
Nginx Stream 配置
Nginx Stream 使用过程中可能还会遇到需要进行负载均衡方式调整、A/B测试、流量镜像、使用TLS加密、记录日志和配置多活等。
负载均衡方法
在upstream 的几种负载均衡方法:
1 | upstream backend_ods { |
load blance | desc |
---|---|
hash $remote_addr consistent |
按client ip(ipv4/ipv6) addrees进行hash和取模(计算可以表示为: mod(hash($remote_addr),upstream_size)), 同一个client的所有会被分发给一个后端节点。问题:单个cleint的并发很高时,会造后端服务节点的负载不均衡。好处:方便跟踪日志和抓包 |
hash $remote_addr$remote_port consistent |
按client ip(ipv4/ipv6) addrees + client port进行hash和取模,可以更好的实现后端节点的负载均衡 |
hash $connection consistent |
按 client 链接到nginx 的 connection serial number 进行hash和取模,这个方式类似于$remote_addr$remote_port |
*这里consistent
常量的作用是避免增加或者删除后端server时候,大量服务断开的问题。参照: consistent parameter
Nginx Stream其它负载均衡方法:least_conn
,least_time
,random
。
Stream 流量镜像
将生产环境的一部分流量转发到指定节点进行压力测试或者灰度测试, 因为nginx 的mirro module是不支持stream模式下的流量复制,这里需要借助使用iptables
实现。
实现复制10.224.18.34:9443的进站流量到10.224.17.246:10095
1 | iptables -t mangle -A PREROUTING -d 10.224.18.34 -dport 9443 -j TEE --gateway 10.224.17.246:10095 |
这里需要配置iptables-servcie
和
Mirroring outbound https traffic w/ iptables
注意:如果是TLS加密数据,镜像后的流量需要解密。
Stream A/B测试
将流量进行切分,执行A/B测试的场景。
配置文件:
1 | stream { |
split_clients
分流算法使用MurmurHash2
- 详情参考ngx_stream_split_clients_module
配置Stream TLS/SSL
如果程序涉及的数据比较机密或者或者网络环境不可信时,需要使用stream_ssl_preread_module
配置TLS 证书进行加密,配置如下:
1 | server { |
- 可能涉及配置证书等操作,请参照HTTP2 TLS加密通信理解与应用
- 跟多配置信息ngx_stream_ssl_module
配置Stream log
在Nginx Stream 调试时,需要输出一些详细日志用于问题定位和检查,需要使用ngx_stream_log_module
打印更多日志信息。
记录请求数据日志:
1 | stream { |
增加对TLS 的日志记录,便于查看client 使用的加密方法等信息:
1 | upstream { |
- 注意:使用yum intall nginx 安装的无法配置 stream log( 缺少
ngx_stream_log_module
) - 跟多配置参数:ngx_stream_log_module
配置多活
使用keepalive 配置多活,这里keepalived + VIP + DNS 实现多活,整个逻辑和实现如下图
Nginx Stream L4 代理遇到的问题
Health Check
Nginx Stream 官方的health check(ngx_stream_upstream_hc_module)需要使用商业订阅, $2500/Year起。社区有一些替代方案: ngx_stream_upstream_health_check
- 注意 ngx_stream_upstream_health_check 方案需要后端程序提供http port (对于微服务很适用)
- 吐槽 PS: HaProxy Health Check 在社区版本是免费提供
后端服务平滑升级会出现 TCP链接断开的问题
为避免增加或者删除后端服务节点时,出现大量TCP 链接重连,建议将loadBalance策略配置为 hash $remote_addr$remote_port consistent
或者类似的,可以减少链接断开的情况,但后端服务重启时部分反向代理到该节点的client 连接依然会断开。这个问题暂时没解决。
参数优化问题
- TCP keepalived 参数设置,优化点如下;
1
2
3
4
5# 允许一定时间的会话保持 避免频繁断开连接
listen 9443 so_keepalive=on so_keepalive=30m::10;
#后端节点链接超时时间,如果所有后端节点存在异常,应快速断开,避免数据堆积
proxy_connect_timeout 10s;
proxy_timeout 30m; - 设置读写缓冲区设置
1
2
3
4
5listen address:9443 ssl sndbuf=128k rcvbuf=128k
server {
preread_buffer_size 1024k
}sndbuf
rcvbuf
可以设置每个 Socket的读写缓冲区大小。
流量镜像的操作非常不方便
如果需要使用该功能,还是推荐使用HaProxy
性能方面
Nginx Stram 性能测试:
1 | 机器: 8核心16G内存 Centos7 |
- 备注:在TCP 反向代理上,HaProxy 在性能方面更有优势
参考
参考文献: http://nginx.org/en/docs/stream/ngx_stream_upstream_module.html#hash
附录 Nginx 安装
检查openssl 版本
1 | openssl version |
OpenSSL 1.0.1e-fips 11 Feb 2013
为了便于TLS1.3等使用,需要将openssl 升级到最新版本 1.1.1
升级openssl
1 | cd ~ |
运行openssl 出现错误:
1 | /usr/local/bin/openssl version |
使用以下步骤修复该问题:
Create links to libssl:
1
2sudo ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/
sudo ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/Finally create link to new openssl
1
sudo ln -s /usr/local/bin/openssl /usr/bin/openssl_latest
测试版本
1
2
3openssl_latest version
OpenSSL 1.1.0f 25 May 2017
Additional tips设置最新的openssl:
1 | cd /usr/bin/ |
检查:
1 | openssl version |
检查和升级zlib
nginx 压缩gzip 使用 zlip库进行压缩。
1 | yun info zlip |
版本是 2.0.7 将其升级到zlib-1.2.11
1 | wget http://zlib.net/zlib-1.2.11.tar.gz |
zlib 升级完成
PCRE
PCRE 用于Nginx正则进行重写要用到, 需要注意nginx 是不支持PCRE2的。这里将其升级到 PCRE 8.44
1 | #nginx 支持的最新 pcre版本是 8.43 |
编译安装 nginx
执行编译
1 | cd ~/nginx-18.0 |
输出:
1 | nginx version: nginx/1.18.0 |
设置防火墙
1 |
|
使用nc
测试stream
在nginx node 可以使用nc -l 10091
启动端口监听,方便进行测试。
client可以使用telnet 也可以使用nc
。
参考: