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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM