负载均衡与反向代理
upstream配置 负载均衡算法 失败重试 健康检查 其它配置 长连接 http反向代理示例 Nginx四层负载均衡
upstream配置
upstream backend{
server 192.268.61.1:9090 weight=1;
server 192.268.61.1:9091 weight=2;
}
upstream 的主配置
ip地址和port:配置上游服务器的ip地址和端口
wight:配置权重、默认1
如上配置、为每三次请求中、有一个请求转发给9090端口、另外两个请求转发给9091端口
然后、可以使用
location / {
proxy_pass http://backend;
}
负载均衡算法
默认采用轮询 round-robin、常用:
1. round-robin:轮询、即以轮询的方式将请求转发到上游服务器、通过配合weight配置可以实现基于权重的轮询
2. ip_hash:根据客户端ip进行负载均衡、即相同的op将负载均衡到同一个upstream server
eg. upstream backend {
ip_hash;
server 192.168.61.1:9080 weight=1;
server 192.168.61.1:9090 weight=2;
}
3. hash key [consistent] 对某一个key进行hash或者使用一致性hash算法进行负载均衡
使用hash算法存在的问题是:当添加或者删除一台服务器时、将导致很多key被重新负载均衡到不同的server、从而导致后端出问题、因此可以考虑一致性hash算法、这样只有少量的key将被均衡到不同的server
upstream backend{
hash $uri;
server 192.168.61.1:9080 weight=1;
server 192.168.61.1:9090 weight=2;
}
一致性hash
upstream backend{
hash $consistent_key consistent; // consistent_key是一致性hash
server 192.168.61.1:9080 weight=1;
server 192.168.61.1:9090 weight=2;
}
此处还可以使用lua来设置一致性hash key
set_by_lua_file $consistent_key "lua_balancing.lua";
lua_balacing.lua代码:
local consistent_key = args.cat
if not consistent_key or consistent_key == '' then
consistent_key = ngx_var.request_uri
end
local value = balancing_cache:get(consistent_key)
if not value then
success, err = balancing_cache:set(consistent_key, 1, 60)
else
newval, err = balancing_cache:incr(consistent_key, 1)
end
若某一个分类的请求量太大、上游服务器可能处理不了这么多的请求、此时可以在一致性hash key后边加上递增的计数器实现类似轮询的算法
if newval > 5000 then
consistent_key = consistent_key .. '_' .. newval
end
4. last_conn
将请求负载均衡到最少活跃连接的上游服务器、若配置的服务器较少、则将转而是要基于权重的轮询算法
商业版nginx还提供了least_time、即基于最小平均时间进行负载均衡
失败重试
主要有两部分配置 upstream server和proxy_pass
upstream backend{
server 192.168.61.1:9080 max_fails=2 fail_timeout=10s weight=1;
server 192.168.61.1:9090 max_fails=2 fail_timeout=10s weight=2;
}
通过配置上游服务器的max_fails和fail_timeout、来指定每个上游服务器、当fail_timeout时间内失败了max_fails次请求、则认为该上游服务器不可用/不存活、然后将摘掉该上游服务器、fail_timeout时间后会再次将该服务器加入到存活上游服务器列表进行重试
location /test{
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
proxy_next_upstream error timeout;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 2;
proxy_pass http://upstream;
add_header upstream_addr $upstream_addr;
}
然后进行proxy相关配置、遇到配置错误时、会重试到下一台上游服务器
健康检查
nginx 默认惰性检查策略、商业版提供了health_check进行主动健康检查、当然也可以集成nginx_upstream_check_module_health__check来进行主动检查
1. tcp心跳检测
upstream backend {
server 192.168.61.9080 wight=1;
server 192.168.61.9090 wight=2;
check interval=3000 rise=1 fail=3 timeout=2000 type=tcp;
}
此处配置使用tcp进行心跳检测
interval检测时间周期
fail检测失败多少次后、上游服务器被标志为不存活
rise检测成功多少次后、被标记为存活、并可以进行处理请求
timeout请求超时配置
2. http心跳检查
upstream backend {
server 192.168.61.9080 wight=1;
server 192.168.61.9090 wight=2;
check interval=3000 rise=1 fail=3 timeout=2000 type=http;
check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
http心跳检测有两个额外配置项、
check_http_send 即检测时发的http请求内容
check_http_expect_alive 当上游服务器返回匹配的响应状态码时、则认为服务器是存活的
注意:要合理设置检测间隔时间、否则、可能会因为心跳检测包太多、造成上游服务器挂掉、同时要设置合理的超时时间
其它配置
1. 域名上游服务器
upstream backend {
server a.cc;
server b.cc;
}
在社区版中、是在nginx解析阶段将域名解析为ip地址并记录到upstream上、当域名对应ip发生变更时、upstream不会动态更新
nginx商业版可以支持动态更新
2. 备份上游服务器
upstream backend{
server 192.168.61.9080 wight=1;
server 192.168.61.9090 wight=2 backup;
}
9090 作为备用上游服务器、只有所有主上游服务器都不存活时、才会将请求转发给备用上游服务器
3. 不可用上游服务器
upstream backend {
server 192.168.61.9080 wight=1;
server 192.168.61.9090 wight=2 down;
}
9090端口服务器设置为永久不可用、当测试或者机器故障是、可以暂时这么配置、来摘掉上游服务器‘
长连接
upstream backend{
server 192.168.61.1:9080 weight=1;
server 192.168.61.1:9090 weight=2 backup;
keepalive 100;
}
通过该指令配置了每个worker进程与上游服务器可缓存的空闲连接的最大数量、超出该值、最近最少使用的连接将被关闭、keepalive 指令不限制Worker进程与上游服务器的总连接、如果超了会作为短链接
若想与上游服务器保持长连接、还必须配置如下:
location / {
# 支持keepalive
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://backend;
}
若是http1.0、则还要发送Connection:Keep-alive请求头
http反向代理示例
1. 全局配置(proxy cache)
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_tmp_file_write_size 256k;
proxy_cache_lock on;
proxy_cache_lock_timeout 200ms; #缓存锁超时时间、超时之后将直接请求后端、结果不缓存
proxy_temp_path /tmp/proxy_temp;
proxy_cache_path /temp/proxy_cache levels=2 keys_zone=cache:512m inactive=5m max_size=8g;
proxy_connection_timeout 5s;
proxy_read_timeout 5s;
proxy_write_timeout 5s;
开启proxy_buffer、缓存内容将存放在tempfs(文件系统内)以提升性能
2. location配置
location backend {
# 设置一致性hash的负载均衡key
set_by_lua_file $consistent_key "/export/App/a.cc/lua/lua_balacing_backend.properties";
# 失败重试机制
proxy_next_upstream error timeout http_500 http_502 http_504;
proxy_next_upstream_timeout 2s;
proxy_next_upstream_tries 2;
# 请求上游服务器
proxy_method GET;
# 不给上游server传递请求体
proxy_pass_request_body off;
# 不给上游server传递请求头
proxy_pass_request_header off;
# 设置上游server的哪些请求头不给client
proxy_hide_header Vary;
# 支持keep_alive
proxy_http_version 1.1;
proxy_set_header Connetion "";
# 给上游server传递refer、cookie和host
proxy_set_header Refer $http_refer;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host a.cc;
proxy_pass http://backend /$1$is_args$args;
}
3. gzip 支持(减小网络传输的数据包的大小)
gzip on;
gzip_min_length 1k;
gzip_buffers 16 16k;
gzip_http_version 1.0;
gzip_proxied any;
gzip_com_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
上边的负载均衡的实现、每次upstream变更、都要手动修改、而且upstram上线、无法自动注册到upstream中、所以、需要有服务的自动注册和发现、将upstream自动注册到nginx上
Consul 是一个开源分布式动态注册与发现系统
具有:1. 服务注册:服务实现者可以用Http API或者DNS的方式、将服务注册到Consul
2. 服务发现:服务实现者可以用Http API或者DNS的方式、获取服务的信息(ip & port等)
3. 故障检测:支持如http、tcp等方式的健康检查
4. K/V存储:使用KV存储、实现动态配置中心、其使用http长轮询实现变更触发和配置更改
5. 多数据中心:支持多数据中心、可以按照数据中心注册和发现服务、既支持消费本地机房服务、又可以避免单数据中心的单点故障
6. Raft算法:实现机器数据一致性
Nginx四层负载均衡
一般采用的是HaProxy、但、一般场景可以使用nginx来解决
1. 静态负载均衡
默认情况下 ngx_stream_core_module 未启用、需要在编译nginx时、指定--with-stream参数
1. stream 指令、在stream模块配置、http负载均衡是在http指令下
stream {
upstream mysql_backend {...}
server {...}
}
2. upstream 配置、类似http upstream
upstream mysql_backend {
server 192.168.61.1:9080 max_fails=2 file_timeout=1s weight=1;
server 192.168.61.1:9090 max_fails=2 file_timeout=1s weight=2;
least_conn;
}
3. server 配置
# 监听端口
listen 80;
# 失败重试
proxy_next_upstream on;
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 0;
# 超时配置
proxy_connect_timeout 1s;
proxy_timeout 1m;
# 限速配置
proxy_upload_rate 0;
proxy_download_rate 0;
#上游服务器
proxy_pass mysql_backend;