Nginx 学习笔记:http代理/负载均衡/长连接/健康检查

Nginx 是一款轻量级的 Web 服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。

在使用中,经常将其用到以下几个方面:

  • 反向代理 SPA/SSR 应用
  • 负载均衡

Ubuntu 配置 Nginx

安装 nginx:

1
sudo apt-get install nginx

重启 nginx 前,需要测试 nginx 配置是否正确:

1
sudo nginx -t

重新加载 nginx:

1
sudo nginx -s reload

不特殊指定,默认加载/etc/conf/nginx.conf 的配置。

Nginx 默认配置解读

对于nginx version: nginx/1.14.0 (Ubuntu)版本的 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
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 768;
# multi_accept on;
}

http {

##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;

# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}


#mail {
# # See sample authentication script at:
# # <http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript>
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}

几个重要的点:

  • user:代表执行 nginx 的用户,可以换成权限更高的用户
  • http/mail:代表 http/邮箱服务的配置
  • include /etc/nginx/conf.d/*.conf:加载 conf.d 下的所有以.conf 结尾的配置文件

在配置的时候,一般都将对应的配置文件放在/etc/nginx/conf.d/

代理 Http(s)服务

xin-tan.com 是 vuepress 构建的,为了提供给用户更好的浏览体验,用 nginx 做服务器,要求如下:

  • 强制 https:监听 80 port,请求转发给 443 port(换协议)
  • 配置 SSL 证书:配置私钥文件和证书文件(一般云厂商申请的 ssl 证书,都有对应说明)
  • 指定 locaiton:和 SPA 应用一致,路由交给前端 router 管理

代码:https://github.com/dongyuanxin/blog/blob/master/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
server {
listen 80;
server_name xin-tan.com;
# nginx最新写法
return 301 https://$server_name$request_uri;

location / {
root /home/ubuntu/data/blog-static;
index index.html index.htm index.nginx-debian.html;
try_files $uri $uri/ =404;
}
}

server {
listen 443 ssl;
#填写绑定证书的域名
server_name xin-tan.com;
#证书文件名称
ssl_certificate /tmp/1_bundle.crt;
#私钥文件名称
ssl_certificate_key /tmp/2.key;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

location / {
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
root /home/ubuntu/data/blog-static;
index index.html index.htm index.nginx-debian.html;
try_files $uri $uri/ =404;
}
}

实现负载均衡

nginx 的优势之一是:可以代理多个服务器。

通俗来说,按照某些规则,将请求分配给对应的服务器。从而实现某些方面(请求量、服务器负载等等)的负载均衡。

基本配置

假设针对 a.com 域名的 http 服务,提供负载均衡。并且有多个后端服务,分别运行在本地服务(也可以是同一 vpc 下、或者远程服务器)的不同端口。

假设这些后端服务都是相同的逻辑,并且是无状态服务。

那么首先需要配置反向代理:

1
2
3
4
5
6
7
8
server {
listen 80;
server_name 193.112.241.232;

location / {
proxy_pass <http://myservers>;
}
}

这里的 myservers 是 upstream 的 name(往下看就明白了)。

负载均衡的各种策略(upstream)

1、普通轮询

1
2
3
4
upstream myservers {
server 127.0.0.1:4445;
server 127.0.0.1:4446;
}

2、按权重轮询

1
2
3
4
upstream myservers {
server 127.0.0.1:4445 weight=10;
server 127.0.0.1:4446 weight=1;
}

3、ip hash:相同的 ip 负载到同一个 upstream server

1
2
3
4
5
upstream myservers{
ip_hash;
server 127.0.0.1:4445 weight=1;
server 127.0.0.1:4446 weight=2;
}

4、一致性 hash

1
2
3
4
5
upstream myservers{
hash $custom_key consistent;
server 127.0.0.1:4445 weight=2;
server 127.0.0.1:4446 weight=1;
}

5、自定义 hash 规则:可以使用 Nginx 变量

1
2
3
4
5
upstream myservers{
hash $uri;
server 127.0.0.1:4445
server 127.0.0.1:4446;
}

配置 HTTP 长连接

为什么要用长连接?

  • 不需要每次 tcp 请求都经历握手和挥手的过程
  • 提高响应请求响应时间,减少 time-wait 状态的 Socket

Nginx 配置思路

先来看请求链路过程是:C 端请求 => Nginx 代理 => 上游的 Server。

所以,Nginx 要做到两头都是长连接:

  • C 端请求 => Nginx 代理:nginx 扮演 server
  • Nginx 代理 => 上游的 Server:naginx 扮演 client

思路和 nginx 在不同过程中的“角色”清除后,剩下就是配置了。

Nginx 配置

C 端到 Nginx

默认配置文件中已有:keepalive_timeout。为 0,禁用长连接;不为 0,代表长连接超时关闭时间。

除此之外,还有常用的:keepalive_requests。默认为 100,为一个长连接能接受的最大请求数。

Nginx 到上游 Server

反向代理配置中,需要支持 keep-alive:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name 193.112.241.232;

location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass <http://myservers>;
}
}

到上游 Server 的配置:

1
2
3
4
5
6
upstream myservers {
server 127.0.0.1:4445;
server 127.0.0.1:4446;
keepalive 100;
}

服务健康检查

为什么要心跳检查?

目的是为了 Server 的健康检查。因为 nginx 支持 4 层和 7 层代理,所以支持 tcp 心跳检查和 http 心跳检查。

nginx 配置

http 心跳检查

1
2
3
4
5
6
7
8
9
upstream myservers {
server 127.0.0.1:4445;
server 127.0.0.1:4446;
# 5s检查一次。检查成功1次,标记server存活;失败5次,标记挂掉。
check interval=5000 rise=1 fail=5 timeout=5000 type=http;
# http 心跳包
check_http_send "HEAD /status HTTP/1.0\\r\\n\\r\\n";
check_http_expect_alive http_2xx http_3xx;
}

tcp 检查

1
2
3
4
5
upstream myservers {
server 127.0.0.1:4445 weight=1;
server 127.0.0.1:4446 weight=2;
check interval=5000 rise=1 fail=5 timeout=5000 type=tcp;
}

参考资料