OpenResty生产环境反向代理和七层负载均衡配置策略

Nginx配置手册

《Nginx配置手册》看这里

nginx.conf生产主配置项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#user  nobody;
#cpu有n个核,就启用n个进程,例如4核处理器,就开启4个进程,最多配置8个;
worker_processes 2;
#多核cpu配置,n核就用n位二进制数字表示哪个内核启用进程
worker_cpu_affinity 01 10;

#error_log logs/error.log;
#error_log logs/error.log notice;
error_log /var/log/nginx/error.log warn;

#pid logs/nginx.pid;



#nginx打开的最大文件句柄数
worker_rlimit_nofile 10240;

events {
#nginx最大连接数,要<=worker_rlimit_nofile,瓶颈会在cpu,设置太大会损耗cpu性能
worker_connections 10240;
#IO模型,linux默认用epoll性能较高
use epoll;
#多个请求到达nginx,设置加锁提高nginx性能,避免nginx进程worker争夺处理网络连接(惊群效应)on/off
accept_mutex on;

}
http {
include mime.types;
default_type application/octet-stream;
charset utf-8;

lua_package_path "/opt/nginx_conf/lualib/?.lua;;";
lua_package_cpath "/opt/nginx_conf/lualib/?.so;;";
include /opt/nginx_conf/server_1.conf;

#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;

#高效传输
sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

gzip on;
gzip_min_length 5k;
gzip_buffers 4 16k;
gzip_comp_level 8;
gzip_types text/css application/xml text/javascript image/jpeg image/png image/gif;
#http header有关,根据浏览器压缩策略进行压缩
gzip_vary on;

proxy_temp_path /tmp/data/nginx;
proxy_cache_path /data/nginx/cache/proxy_cache levels=1:2 keys_zone=ec:200m max_size=1g;

Nginx基于SS/TLS的HTTPS安全请求配置

/opt/nginx_conf/server_1.conf配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#上游Tomcat服务器
upstream backend {
server 192.168.1.232:8080;
}

server {
listen 81;
server_name _;

location /hello/test {
default_type 'text/html';
content_by_lua_file /opt/nginx_conf/lua/test.lua;
}
}
#增加ssl请求的443端口和反向代理配置
server {
listen 443;
server_name localhost;
#开启ssl验证,并配置私钥和公钥证书
ssl on;
ssl_certificate /usr/servers/nginx/conf/server.crt;
ssl_certificate_key /usr/servers/nginx/conf/server.key;
location /{
proxy_pass http://backend;
}

}

使用openssl生成服务器私钥server.key和客户端公钥证书:

1
2
3
4
5
6
7
8
9
#生成服务器端私钥
openssl genrsa -des3 -out server.key 1024
#创建签名请求的csr证书,csr保存了公钥
openssl req -new -key server.key -out server.csr
#去掉使用私钥时的口令验证
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
#生成X509公钥证书server.crt,并绑定私钥server.key和公钥信息server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

配置Nginx的七层负载均衡功能时,server_1.conf文件中的反向代理会映射到上游应用服务器(Tomcat),Nginx在443端口接到https请求后,转发给上游Tomcat服务器8080端口,Tomcat需要支持从Nginx转发过来的https请求,在Tomcat的server.xml配置文件Connector 8080节点增加对443端口的跳转即可,并不需要开启Tomcat对https请求的证书安全验证。

1
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="443" proxyPort="443" />

如果使用Springboot启动内嵌Tomcat,则增加对内嵌Tomcat的代码配置:

1
2
3
4
5
6
7
8
@Configuration
public class WebMvcConfiguration implements TomcatConnectorCustomizer{
@Override
public void customize(Connector connector) {
connector.setRedirectPort(443);
connector.setProxyPort(443);
}
}

Nginx反向代理缓存配置降低上游服务器压力

代理分为正向代理和反向代理,简言之,正向代理是指代理客户端请求,反向代理是指代理服务器端服务。Nginx作为七层负载均衡服务器,主要任务是分发从客户端到达的http请求到上游服务器集群。为了减少到达上游服务器的并发请求数量,可以在Nginx进行反向代理的缓存全局配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 256k;
proxy_cache_lock on;
proxy_cache_lock_timeout 200ms;
#/tmpfs为内存文件系统
proxy_temp_path /tmpfs/proxy_temp;
proxy_cache_path /tmpfs/proxy_cache levels=1:2 keys_zone=cache:512m inactive=5m max_size=8g;
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;

Nginx常用的七层负载均衡配置策略

Step1.配置upstream上游服务器和负载均衡算法

要实现负载均衡,首先,要配置Nginx反向代理的上游服务器地址,并配置响应的负载均衡算法。Nginx支持的负载均衡算法有:轮询(round-robin)、IP哈希(ip_hash)、特定值哈希(hash $key)、特定值一致性哈希(hash $key consistent)、最少活跃连接(least_conn),商业版Nginx还支持最少平均响应时间(least_time)。其次,Nginx负载均衡支持对每个代理服务器的请求权重(weight=n)、失败重试(max_fails=n)、连接超时(fail_timeout=ns)、备用(backup)、下线(down)、心跳检测的可选配置项,配合负载均衡算法,实现高可用、高性能的负载均衡。

1
2
3
4
5
6
7
8
9
10
11
12
13
#在nginx配置文件的http模块中配置upstrem模块,并定义一个名字name,在location指向name进行负载均衡。
upstream backend {
#配置负载均衡算法
hash $consistent_key consistent;
#反向代理的上游服务器集群地址
server 192.168.1.210:8080 max_fails=2 fail_timeout=30s weight=1;
server 192.168.1.211:8080 max_fails=2 fail_timeout=30s weight=2;
#反向代理的上游服务器集群宕机,连接到备用机提供服务
server 192.168.1.213:8080 max_fails=2 fail_timeout=30s weight=3 backup;
#心跳检测,interval检测间隔时间(s),rise被检测到存活的次数即可正常提供服务,
#fall被检测到失败的次数标记为服务器不存活,timeout检测请求超时配置
check interval=5000 rise=1 fall=3 timeout=2000 type=tcp;
}

Step2.使用反向代理开启负载均衡

创建一个针对URL的反向代理配置文件/usr/local/common/lua_scripts/hello/hello.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#/xxx是需要进行负载均衡访问的path
location ~ /xxx/(.*)$ {
#backend是配置对上游服务器进行负载均衡算法的名字,$1表示正则表达式(.*)匹配到的内容
#$is_args如果是get请求有参数代表?,并且用$args传送参数值
proxy_pass http://backend/$1$is_args$args;
#如果backend需要根据某一个变量参数($consistent_key)进行负载均衡,则在此处设置;否则,忽略;
#OpenResty支持lua脚本,可以通过lua脚本对参数进行计算
set_by_lua_file $consistent_key "/usr/local/common/lua_scripts/hello/lua/lua_balancing.lua";
#失败重试配置
proxy_next_upstream error timeout http_500 http_502 http_504
proxy_next_upstream_timeout 2s;
proxy_next_upstream_tries 2;

#请求上游服务器的Http Request Method
proxy_method GET;
#是否向上游服务器器传递请求体
proxy_pass_request_body off;
#是否向上游服务器传递请求头
proxy_pass_request_headers off;
#设置上游服务器的哪些请求头信息不发送给客户端
proxy_hide_header Vary;
proxy_http_version 1.1;
#按照需要传递Referer、Cookie、Host
proxy_set_header Connection "";
proxy_set_header Referer $http_referer;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host 192.168.1.212:8080

}

Step3.对负载均衡的$key进行计算

Nginx添加ngx_http_core模块后,在Nginx配置文件中就可以使用相关的Http参数值参与负载均衡算法的计算。$key变量的值可以是Nginx支持的内建变量有$uri(解码后不带参数)、$request_uri(未解码包含参数)、$arg_XXX(未解码的参数XXX,XXX不区分大小写),还支持Nginx内建的常量。OpenResty除了支持Nginx包含的各模块中的变量和常量,还支持Lua脚本对变量进行计算,生产环境中常用

在nginx.conf中http模块中使用lua模块提供的功能配置缓存blcache,在lua脚本中可以使用这个缓存:

1
2
3
4
5
6
7
8
http {
lua_shared_dict blcache 128m;


lua_package_path "/usr/local/common/lua_scripts/hello/lualib/?.lua;;";
lua_package_cpath "/usr/local/common/lua_scripts/hello/lualib/?.so;;";
include /usr/local/common/lua_scripts/hello/hello.conf;
...

/usr/local/common/lua_scripts/hello/lua/lua_balancing.lua脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
local uri_args = ngx.req.get_uri_args()
local consistent_key = uri_args.ecourseId
if not consistent_key or consistent_key == '' then
consistent_key = ngx.var.request_uri
end
local balancing_cache = ngx.shared.blcache
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
if newval and newval > 5000 then
consistent_key = consistent_key..'_'..newval
end
return consistent_key

Nginx内建全局常量:转自Nginx变量使用方法详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
arg_PARAMETER #这个变量包含GET请求中,如果有变量PARAMETER时的值。
args #这个变量等于请求行中(GET请求)的参数,如:foo=123&bar=blahblah;
binary_remote_addr #二进制的客户地址。
body_bytes_sent #响应时送出的body字节数数量。即使连接中断,这个数据也是精确的。
content_length #请求头中的Content-length字段。
content_type #请求头中的Content-Type字段。
cookie_COOKIE #cookie COOKIE变量的值
document_root #当前请求在root指令中指定的值。
document_uri #与uri相同。
host #请求主机头字段,否则为服务器名称。
hostname #Set to themachine’s hostname as returned by gethostname
http_HEADER
is_args #如果有args参数,这个变量等于”?”,否则等于”",空值。
http_user_agent #客户端agent信息
http_cookie #客户端cookie信息
limit_rate #这个变量可以限制连接速率。
query_string #与args相同。
request_body_file #客户端请求主体信息的临时文件名。
request_method #客户端请求的动作,通常为GET或POST。
remote_addr #客户端的IP地址。
remote_port #客户端的端口。
remote_user #已经经过Auth Basic Module验证的用户名。
request_completion #如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty)。
request_method #GET或POST
request_filename #当前请求的文件路径,由root或alias指令与URI请求生成。
request_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。不能修改。
scheme #HTTP方法(如http,https)。
server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
server_addr #服务器地址,在完成一次系统调用后可以确定这个值。
server_name #服务器名称。
server_port #请求到达服务器的端口号。
谢谢你请我吃糖果