bboyjing's blog

跟开涛学架构二【Nginx长连接】

本章节来学习一下如何配置Nginx与上游服务器(real_server)的长连接。本人对这一块也不是很懂,如果只是照着书本添两个配置,可能也达不到学习的效果,下面我就按照自己的方式来浅析下这部分内容。

服务端长连接支持

要想支持长连接,需要客户端(Nginx)和服务端(real_server)都支持才行,我们就先来看下服务端对长连接支持的情况。使用real_server_1项目来做测试,其容器为Springboot内嵌的Tomcat,提供服务的协议为HTTP 1.1,默认支持长连接。在没有修改配置的情况下,连接默认存活时间为60秒,对应配置为server.connection-timeout。下面就来验证

使用netcat发TPC包测试

  • 用HTTP 1.0来请求服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    > nc localhost 8081
    GET / HTTP/1.0
    HTTP/1.1 200
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 18
    Date: Sat, 02 Sep 2017 13:25:15 GMT
    Connection: close
    from real server 1%

    使用不带keep-alive的HTTP 1.0来请求,接收到响应后请求就直接close了,这种情况就属于短连接。另外从返回的头信息里能够看出服务端协议为HTTP/1.1。利用抓包工具再来看下整个过程是什么样的,下图是Wireshark抓出来的包:
    hunger_1
    图中可以看出整个握手过程,以及请求完成后服务端立刻发送了FIN包,主动关闭了连接。

  • 用带keep-alive的HTTP 1.0来请求服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > nc localhost 8081
    GET / HTTP/1.0
    Connection: keep-alive
    HTTP/1.1 200
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 18
    Date: Sun, 03 Sep 2017 07:34:24 GMT
    Connection: keep-alive
    from real server 1

    可以看到服务端返回的响应头加上了Connection: keep-alive,该连接并没有立刻关闭,可以接着发送请求。等服务端超时时间到了之后会发送FIN包,关闭连接。

  • 用HTTP 1.1来请求服务端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    > nc localhost 8081
    GET / HTTP/1.1
    Host: localhost
    HTTP/1.1 200
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 18
    Date: Sun, 03 Sep 2017 08:34:42 GMT
    from real server 1

    返回的响应头并没有Connection信息,但是连接依然保持着,可见这是HTTP 1.1默认行为。

由此,可以确认real_server在不需要修改任何配置的情况下,支持HTTP长连接。

Nginx长连接支持

首先我们来看看默认配置下,Nginx与上游服务器的连接情况,目前nginx部分配置如下:

1
2
3
4
5
6
7
8
9
10
upstream real_server {
server localhost:8081;
server localhost:8082;
}
server {
listen 80;
location / {
proxy_pass http://real_server;
}
}

下面直接请求Nginx

1
2
3
4
5
6
7
8
9
10
11
12
> nc localhost 80
GET / HTTP/1.1
Host: localhost
HTTP/1.1 200
Server: openresty/1.11.2.5
Date: Sun, 03 Sep 2017 12:22:49 GMT
Content-Type: text/plain;charset=UTF-8
Content-Length: 18
Connection: keep-alive
from real server 1

首先可以看出客户端和Nginx之间默认是HTTP长连接(现在主流浏览器都是HTTP 1.1吧),再看看Wireshark抓出来的包:
hunger_2
可以看到Nginx对real_server_1的请求默认走的是HTTP/1.0,完成之后立即发送了一个FIN包,来主动断开连接。由此可以得出结论,Nginx对上游服务器的请求默认是短连接。下面添加支持长连接的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream real_server {
server localhost:8081;
server localhost:8082;
keepalive 16;
}
server {
listen 80;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://real_server;
}
}

使用和上面同样的方式请求Nginx,直接来看抓的包:
hunger_3
此时Nginx对real_server_1的请求走的是HTTP/1.1了,请求完成之后没有任何其他动作,从time line可以看出60秒之后real_server_1发出了一个FIN包来关闭连接。至此,证明Nginx和上游服务器的长连接配置成功。稍微解释下添加的三个配置的意思:

  • keepalive 表示每个worker进程与上游服务器可缓存的最大空闲连接数。当超出该数量时,最近最少使用的连接将被关闭。不过,该数量不会限制worker进程可以打开的总连接数,超了的将作为短连接处理
  • proxy_http_version 将请求协议改成HTTP 1.1
  • proxy_set_header 如果还是使用HTTP 1.0的话,需要该配置项改成Connection “keep-alive”

这一章节就到此为之了。