WebSocket :Nginx+WebSocket內部路由策略推送服務器的實現(附可生產環境應用代碼)

目錄

1.項目背景

前幾天寫了一篇WebSocket推送的博客:WebSocket :用WebSocket實現推送你必須考慮的幾個問題 支持的連接數大概幾千個,具體數量依賴於tomcat能併發的線程數,但很多時候生產環境應用的話幾千個肯定是不行的,所以本問介紹Nginx+WebSocket的實現思路及代碼.

2.實現思路

依照設計模式中的 迪米特法則 外部調用模塊來講要儘量少的參與推送模塊的邏輯,以達到解耦的目的,所以我們雖然通過Nginx+WebSocket做了集羣策略,但是不應該讓外部感知.對於外部調用模塊來講你是否應用集羣與我調用你無關.

大概實現思路是這樣的,推送服務要把不是本機的請求內部路由到相應兄弟服務器.很多同學有疑問了爲什麼要路由呢,Nginx到任意一個節點處理不是就可以了. 大家注意哈,http實現了無狀態請求,但是對於ws來講tcp長連接顯然是一個有狀態請求,舉個例子:server A連接client a,你想通過server B給client a發消息是做不到的,因爲tcp連接在server A上.

設計圖:
這裏寫圖片描述

連接過程: 所有client連接地址均爲Nginx地址,但是實際tcp連接是建立在具體服務器上的.連接完成後redis中要存儲對應用戶的serverId和SessionId(WsSession 是ws用來標識具體連接的).

發送消息過程:外部調用模塊將消息發送到Nginx,假設發送消息的請求發送到了Server B上,那麼Server B需要查出具體用戶當前所連接的服務器,將請求路由轉發到兄弟服務器上去.

3.源碼地址

下載地址
http://download.csdn.net/download/shangmingtao/9920532

4.可優化的點

1.路由轉發方式: 現在實現是用http轉發的,效率很低,可以採用redis PUB/SUB方式 或者 rabbitMQ等.
2.路由轉發內容: 我先再路由轉發的是Client的userId+platform ,爲的是能複用外部調用模塊訪問的接口.其實這裏轉發sessionId就可以了.
3.redis存儲用戶信息當前是序列化進去的.最好用hash這種數據類型.

5.Nginx配置及說明

user  nobody;
worker_processes 1;

events {
    worker_connections  8192; #這個要大一些
}


http {

    upstream ws{
        server 127.0.0.1:18080;
        server 127.0.0.1:28080;
    }

        server {

             listen 81;
             server_name localhost;

 #           動靜分離處理
 #           location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ {
 #                   root html;
 #          }


             location ~/WSPush {
                proxy_pass http://ws;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host:$server_port; #這個用來透傳用戶http請求頭的,因爲我代碼裏調用了request.getServerName()方法,如果不加個配置,取出來是http://ws
                proxy_read_timeout 30m;#這裏一定不要忘了改,默認1分鐘後nginx會斷開ws
            }
        }
}
發佈了41 篇原創文章 · 獲贊 35 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章