Java WebSocket 使用時需要注意的地方
最近在做一個專案,需要用WebSocket與另外一個平臺建立通訊,來獲取專案業務需要的實時資料,因此專案一啟動,後臺就要與另外一個平臺建立WebSocket連線並且要保證他們的之間有且只有一條持續暢通可用的連線(就是要保證這條連線不能斷開,一斷開就要嘗試進行重連),說說我在這個過程中,遇到的一些問題以及解決的方法:
1、WebSocket連線正常,部分請求無響應
原因分析:
服務端/客戶端接收到客戶端/服務端一次性發來的幾百條或更多的請求,瞬間都堆積在會話的緩衝區,又沒做多執行緒處理,並且每接收到一條請求還要查詢阿里雲伺服器資料庫,加上網路頻寬過小,處理一條請求就要花費幾十秒;導致執行緒佇列嚴重堵塞,無法及時響應處理後續的其他請求。
解決方法:
使用了執行緒池開啟多條執行緒同時進行處理,將資料庫配置設定為127.0.0.1,這樣就不會經過公網繞一圈回來,這樣大大縮短了一條請求處理要花費的時間,由之前的幾十秒縮短為幾百毫秒。
// 建立執行緒池
//private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
注意幾種執行緒池的區別,cachedThreadPool只有非核心執行緒,最大執行緒數很大,它會為每一個任務新增一個新的執行緒,它有一個超時機制,當空閒的執行緒超過60s內沒有用到的話,就會被回收。cachedThreadPool缺點就是沒有考慮到系統的實際記憶體大小。fixedThreadPool是一個可以指定執行緒數的執行緒池,有核心的執行緒,裡面有固定的執行緒數量,響應的速度快。正規的併發執行緒,多用於伺服器。核心執行緒是沒有超時機制的,佇列大小沒有限制,除非執行緒池關閉了核心執行緒才會被回收。還有singleThreadPoll、scheduledThreadPoll這裡就不做過多的介紹了。
@OnMessage
public void onMessage(String datas,Session session) {
Runnable t = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// 業務程式碼
}
};
//cachedThreadPool.submit(t);
fixedThreadPool.submit(t);
}
注意,要給session加上同步鎖,否則會出現多個執行緒同時往同一個session寫資料,導致報錯的情況。
public void send(String data) throws Exception {
synchronized (session) {
session.getBasicRemote().sendText(data);
}
}
2、發現WebSocket連線老是每隔一、兩分鐘就斷開重連
原因分析:
一段時間內,WebSocket連線無資料傳輸就會自動斷開連線
解決方法:
增加心跳機制維持連線,每隔一段時間就向服務端傳送一次自定義請求,或者呼叫sendPing()來保持住連線。
3、WebSocket定時傳送sendPing()後,還會反覆出現接收/傳送幾個請求就斷開連線的情況
原因分析:
無論是作服務端還是客戶端,發現每次都是接收到同一個請求的資訊後連線就斷開了,經過反覆的摸索發現,是由於接收到的這個請求傳輸的資料量過大,超出了WebSocket會話接收資訊的緩衝區的大小(可使用session.getMaxTextMessageBufferSize()檢視緩衝大小,預設為8192),引起的WebSocket連線的異常斷開。
解決方法:
重新設定WebSocket緩衝區大小,
int maxSize = 200 * 1024;// 200K
// 可以緩衝的傳入二進位制訊息的最大長度
session.setMaxBinaryMessageBufferSize(maxSize);
// 可以緩衝的傳入文字訊息的最大長度
session.setMaxTextMessageBufferSize(maxSize);
Linux公社的RSS地址 :https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址:https://www.linuxidc.com/Linux/2019-02/156792.htm