
使用使用了代理服務器
如果使用了Nginx,則需要開啟ng支持websocket,一般配置如下:
<code>$ vim /usr/local/nginx/conf/nginx.conf
# 在http上下文中增加如下配置,確保Nginx能處理正常http請求。
http{
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
#ip_hash;
server localhost:8010;
server localhost:8011;
}
# 以下配置是在server上下文中添加,location指用於websocket連接的path。
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/yourdomain.log;
location / {
proxy_pass http://websocket;
proxy_read_timeout 30s; //超時自動斷開
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
\t\t}
\t}
}/<code>
是否開啟了心跳
設置心跳的好處:是可以將閒置較久或無用的連接自動斷開; 自己不用維護;
服務端開啟心跳,代碼如下:
<code>ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
te.setPoolSize(1);
te.setThreadNamePrefix("ws-heartbeat-thread-");
te.initialize();
registry.enableSimpleBroker( "/topic")
.setHeartbeatValue(new long[]{HEART_BEAT,HEART_BEAT}).setTaskScheduler(te);/<code>
建立連接之後顯示的客戶端和服務端心跳的信息如下:
>>> CONNECT
direction:2
clientId:1000000020184101
accept-version:1.1,1.0
heart-beat:10000,0 // 客戶端連接時的心跳設置
<<< CONNECTED
version:1.1
heart-beat:5000,5000 // 服務端建立連接後的心跳設置
user-name:yttqceuw
官網說明如下:
CONNECT
heart-beat:
CONNECTED:
heart-beat:
For heart-beats from the client to the server:
if
otherwise, there will be heart-beats every MAX(
In the other direction,
簡單點說就是,
服務端開啟發送心跳之後,會有幾個地方需要注意(會自動斷開):
- 如果服務端設置了發送心跳(
> 0),間隔為5s, 假如客戶端也設置了發送心跳( ),間隔為10s,那麼建立連接後,客戶端發送的心跳間隔就為10s (MAX( , )),如果任何一方發送消息的時間間隔超過了Nginx配置的超時時間(比如是 30s),那麼ng會自動斷開連接 。 - 服務端設置心跳之後,會啟動一個定時任務(HeartbeatTask),執行間隔為(min(
, )), 任務的執行內容為服務端發送心跳,以及檢查連接無交互的時間間隔是否超過了 (MAX( , )),如果超過了,則服務端會主動斷開連接,具體源碼如下:

SimpleBrokerMessageHandler.java
總結:
開啟心跳後會有很多限制,所以需綜合考慮是否開啟,如果不開啟,可自維護心跳機制(服務端主動發送自定義的心跳信息)。
服務端主動斷開
服務端向客戶端發送消息時,如果滿足下面兩個條件,則服務端會主動斷開(closeStatus=4500):
- 服務端發送消息的時間超過指定時間(默認為10s,可通過 sendTimeLimit設置);
- 服務端發送消息的大小超過指定大小(默認為512K,可通過 sendBufferSizeLimit設置);
具體配置代碼如下:
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setSendBufferSizeLimit(512 * 1024); // 512K
registration.setSendTimeLimit(10 * 10000); // 10s
}
查看連接斷開的原因
斷開枚舉類型見: org.springframework.web.socket.CloseStatus
獲取斷開連接的事件,查看具體的code:
@EventListener(SessionDisconnectEvent.class)
public void handleWebsocketDisconnectListner(SessionDisconnectEvent event) {
log.info("session closed : sessionId={}, status={}", event.getSessionId(), event.getCloseStatus());
}
閱讀更多 架構即人生 的文章