引言
WebSocket
在云服务器上的配置,会出现一些异常情况,例如:WebSocket无法正常访问到,WebSocket断开连接等。
本文意在解决上述出现的一些故障现象。
1. Nginx 支持WebSocket的配置
server {
listen 80;
#域名
server_name localhost;
location /sell {
proxy_pass http://127.0.0.1:8080/; // 代理转发地址
proxy_http_version 1.1;
proxy_read_timeout 3600s; // 超时设置
// 启用支持websocket连接
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
重要的是这两行,它表明是websocket
连接进入的时候,进行一个连接升级将http
连接变成websocket
的连接。
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout; 表明连接成功以后等待服务器响应的时候,如果不配置默认为60s;
proxy_http_version 1.1; 表明使用http版本为1.1
据参考资料 : nginx配置websocket(官方)来编写一份标准配置文件。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream wsbackend{
server ip1:port1;
server ip2:port2;
keepalive 1000;
}
server {
listen 20038;
location /{
proxy_http_version 1.1;
proxy_pass http://wsbackend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600s;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
表示的是
1. 如果 $http_upgrade 不为 '' (空),则 $connection_upgrade 为 upgrade
2. 如果 $http_upgrade 为 '' (空),则 $connection_upgrade 为 close
upstream wsbackend{
server ip1:port1;
server ip2:port2;
keepalive 1000;
}
表示的是 nginx负载均衡
1. 两台服务器 (ip1:port1)和(ip2:port2)
2. keepalive 1000 表示的是每个nginx进程中上游服务器保持的空闲连接,当空闲连接过多时,会关闭最少使用的空闲连接.当然,这不是限制连接总数的,可以想象成空闲连接池的大小.设置的值应该是上游服务器能够承受的
server {
listen 80;
location /{
proxy_http_version 1.1;
proxy_pass http://wsbackend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600s;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
表示的是监听的服务器的配置
1. listen 80 表示 nginx 监听的端口
2. locations / 表示监听的路径(/表示所有路径,通用匹配,相当于default)
3. proxt_http_version 1.1 表示反向代理发送的HTTP协议的版本是1.1,HTTP1.1支持长连接
4. proxy_pass http://wsbackend; 表示反向代理的uri,这里可以使用负载均衡变量
5. proxy_redirect off; 表示不要替换路径,其实这里如果是/则有没有都没关系,因为default也是将路径替换到proxy_pass的后边
6. proxy_set_header Host $host; 表示传递时请求头不变, $host是nginx内置变量,表示的是当前的请求头,proxy_set_header表示设置请求头
7. proxy_set_header X-Real-IP $remote_addr; 表示传递时来源的ip还是现在的客户端的ip
8. proxy_read_timeout 3600s; 表示两次请求之间的间隔超过 3600s 后才关闭这个连接,默认的60s.自动关闭的元凶
9. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 表示X-Forwarded-For头不发生改变
10. proxy_set_header Upgrade $http_upgrade; 表示设置Upgrade不变
11. proxy_set_header Connection $connection_upgrade; 表示如果 $http_upgrade为upgrade,则请求为upgrade(websocket),如果不是,就关闭连接
简要版本:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
2. Nginx代理webSocket经常出现中断的解决方案, 如何保持长连接
原因是: nginx
等待客户端第一次通讯和第二次通讯的时间差,超过了它设定的最大等待时间,简单来说就是,超时,所以就断了webSocket
连接,开始上解决步骤。
解决方案一
其实只要配置
nginx.conf
的对应localhost
里面的这几个参数就好
- proxy_connect_timeout
- proxy_read_timeout
- proxy_send_timeout
http {
server {
location / {
root html;
index index.html index.htm;
proxy_pass http://webscoket;
proxy_http_version 1.1;
proxy_connect_timeout 4s; #配置点1
proxy_read_timeout 60s; #配置点2,如果没效,可以考虑这个时间配置长一点
proxy_send_timeout 12s; #配置点3
proxy_set_header Upgrade $http_upgrade; #这是webSocket的配置,与此解决方案无关
proxy_set_header Connection "Upgrade"; #这是webSocket的配置,与此解决方案无关
}
}
}
关于配置点2的解释
备注:这个是服务器对客户端等待最大的时间,也就是说,当你webSocket
使用nginx
转发的时候,对于上面的配置点2来说,如果60秒内没有通讯,依然是会断开的,所以,你可以按照你的需求来设定。
举例:
比如说,我设置了10分钟,那么如果我10分钟内有通讯,或者10分钟内有做心跳的话,是可以保持连接不中断的,详细看个人需求
解决方案二
发心跳包,原理就是在有效的再读时间内进行通讯,重新刷新再读时间
3. Nginx超时设置详解
上面所讲的超时设置,显得有些模糊,索性将涉及到的超时设置一并归拢了吧。
Nginx
处理的每个请求均有相应的超时设置。如果做好这些超时时间的限定,判定超时后资源被释放,用来处理其他的请求,以此提升 Nginx
的性能。
1. client_header_timeout
客户端向服务端发送一个完整的 request header
的超时时间。如果客户端在指定时间内没有发送一个完整的 request header
,Nginx
返回 HTTP 408(Request Timed Out)。
语法
client_header_timeout time
默认值
60s
上下文
http, server
说明
指定等待client
发送一个请求头的超时时间(例如:GET / HTTP/1.1).仅当在一次read
中,没有收到请求头,才会算成超时。如果在超时时间内,client
没发送任何东西,nginx
返回HTTP
状态码408(“Request timed out”)
接收客户端header
超时, 默认60s, 如果60s内没有收到完整的http包头, 返回408
Syntax: client_header_timeout time;
Default: client_header_timeout 60s;
Context: http, server
Defines a timeout for reading client request header. If a client does not transmit the entire header within this time,
the 408 (Request Time-out) error is returned to the client.
2. client_body_timeout
指定客户端与服务端建立连接后发送 request body
的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx
返回 HTTP 408(Request Timed Out)。
语法
client_body_timeout time
默认值
60s
上下文
http, server, location
说明
该指令设置请求体(request body)的读超时时间。仅当在一次readstep
中,没有得到请求体,就会设为超时。超时后,nginx
返回HTTP状态码408(“Request timed out”)
接收客户端body超时, 默认60s, 如果连续的60s内没有收到客户端的1个字节, 返回408
Syntax: client_body_timeout time;
Default:
client_body_timeout 60s;
Context: http, server, location
Defines a timeout for reading client request body. The timeout is set only for a period between two successive read operations, not for the transmission of the whole request body.
If a client does not transmit anything within this time,
the 408 (Request Time-out) error is returned to the client.
3. keepalive_timeout
HTTP
是一种无状态协议,客户端向服务器发送一个 TCP
请求,服务端响应完毕后断开连接。
如果客户端向服务器发送多个请求,每个请求都要建立各自独立的连接以传输数据。
HTTP
有一个 KeepAlive
模式,它告诉 webserver
在处理完一个请求后保持这个 TCP
连接的打开状态。若接收到来自客户端的其它请求,服务端会利用这个未被关闭的连接,而不需要再建立一个连接。
KeepAlive
在一段时间内保持打开状态,它们会在这段时间内占用资源。占用过多就会影响性能。
Nginx
使用 keepalive_timeout
来指定 KeepAlive
的超时时间(timeout
)。指定每个 TCP
连接最多可以保持多长时间。Nginx
的默认值是 75 秒,有些浏览器最多只保持 60 秒,所以可以设定为 60 秒。若将它设置为 0,就禁止了 keepalive
连接。
语法
keepalive_timeout timeout [ header_timeout ]
默认值
75s
上下文
http, server, location
说明
第一个参数指定了与client
的keep-alive
连接超时时间。服务器将会在这个时间后关闭连接。
可选的第二个参数指定了在响应头Keep-Alive: timeout=time
中的time
值。这个头能够让一些浏览器主动关闭连接,这样服务器就不必要去关闭连接了。没有这个参数,nginx
不会发送Keep-Alive
响应头(尽管并不是由这个头来决定连接是否“keep-alive”)
两个参数的值可不相同
keepalive
时间,默认75s,通常keepalive_timeout
应该比client_body_timeout
大
Syntax: keepalive_timeout timeout [header_timeout];
Default:
keepalive_timeout 75s;
Context: http, server, location
The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side. The zero value disables keep-alive client connections.
The optional second parameter sets a value in the “Keep-Alive: timeout=time” response header field. Two parameters may differ.
The “Keep-Alive: timeout=time” header field is recognized by Mozilla and Konqueror.
MSIE closes keep-alive connections by itself in about 60 seconds.
4. lingering_timeout
语法
lingering_timeout time
默认值
5s
上下文
http server location
说明
lingering_close
生效后,在关闭连接前,会检测是否有用户发送的数据到达服务器,如果超过lingering_timeout
时间后还没有数据可读,就直接关闭连接;否则,必须在读取完连接缓冲区上的数据并丢弃掉后才会关闭连接。
Syntax: lingering_timeout time;
Default:
lingering_timeout 5s;
Context: http, server, location
When lingering_close is in effect, this directive specifies the maximum waiting time for more client data to arrive. If data are not received during this time,
the connection is closed. Otherwise, the data are read and ignored, and nginx starts waiting for more data again.
The “wait-read-ignore” cycle is repeated, but no longer than specified by the lingering_time directive.
5. resolver_timeout
语法
resolver_timeout time
默认值
30s
上下文
http server location
说明
该指令设置DNS解析超时时间
域名解析超时,默认30s
Syntax: resolver_timeout time;
Default:
resolver_timeout 30s;
Context: http, server, location
Sets a timeout for name resolution, for example:
resolver_timeout 5s;
6. proxy_connect_timeout
语法
proxy_connect_timeout time
默认值
60s
上下文
http server location
说明
该指令设置与upstream server
的连接超时时间,有必要记住,这个超时不能超过75
秒。
这个不是等待后端返回页面的时间,那是由proxy_read_timeout
声明的。如果你的upstream
服务器起来了,但是hanging
住了(例如,没有足够的线程处理请求,所以把你的请求放到请求池里稍后处理),那么这个声明是没有用的,由于与upstream
服务器的连接已经建立了。
nginx
与upstream server
的连接超时时间
Syntax: proxy_connect_timeout time;
Default:
proxy_connect_timeout 60s;
Context: http, server, location
Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.
7. proxy_read_timeout
语法
proxy_read_timeout time
默认值
60s
上下文
http server location
说明
该指令设置与代理服务器的读超时时间。它决定了nginx
会等待多长时间来获得请求的响应。这个时间不是获得整个response
的时间,而是两次reading
操作的时间。
nginx
接收upstream server
数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭
Syntax: proxy_read_timeout time;
Default:
proxy_read_timeout 60s;
Context: http, server, location
Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations,
not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.
8. proxy_send_timeout
语法
proxy_send_timeout time
默认值
60s
上下文
http server location
说明
这个指定设置了发送请求给upstream
服务器的超时时间。超时设置不是为了整个发送期间,而是在两次write
操作期间。如果超时后,upstream
没有收到新的数据,nginx会关闭连接
nginx
发送数据至upstream server
超时, 默认60s, 如果连续的60s内没有发送1个字节, 连接关闭
Syntax: proxy_send_timeout time;
Default:
proxy_send_timeout 60s;
Context: http, server, location
Sets a timeout for transmitting a request to the proxied server. The timeout is set only between two successive write operations,
not for the transmission of the whole request. If the proxied server does not receive anything within this time, the connection is closed.
9. proxy_upstream_fail_timeout(fail_timeout)
语法
server address [fail_timeout=30s]
默认值
10s
上下文
upstream
说明
Upstream
模块下 server
指令的参数,设置了某一个upstream
后端失败了指定次数(max_fails)后,该后端不可操作的时间,默认为10秒