一、 項目介紹
我們很容易可以使用Spring-boot來搭建一個支持websocket的應用,用來實現基於HTML5的客戶端之間進行消息的接收和推送。但是在實際應用的部署時,客戶端和應用服務器之間總會用到Nginx或者Apache來做反向代理,來實現負載均衡。
用Nginx舉個例子來說,我們使用輪詢的方式,將客戶端的請求分發到後端3臺web應用服務器上(Server1Server1,Server2Server2,Server3Server3)。Client1Client1第一次通過ws://www.xxx.com/wss
這樣一個地址與應用服務器進行握手。Nginx會將請求發送給Server1Server1,Client1Client1會與Server1Server1建立一個websocket的Session1Session1。之後Client2Client2、Client3Client3執行同樣的操作。握手請求會被分發到Server2Server2和Server3Server3上,並分別在服務器上創建了各自的websocket會話Session2Session2和Session3Session3。
好的,我們的問題來了。我們的3個客戶端的3個websocket會話分別在3臺服務器上。且不說如何實現客戶端互相通知上下線狀態。單說如果系統中需要給其中一個客戶端推送一條消息,我們怎麼知道這個客戶端在哪臺服務器上建立了websocket聯機呢?
如下的項目中,我們將使用Kafka這樣一個分佈式消息中間件來解決上面的問題。
項目地址:點擊這裏
二、需要具備的知識背景
如果想很好的理解本文所涉及到的內容,可能需要讀者具備一下知識背景。
- Spring-Boot框架
- Docker
- Zookeeper
- Kafka
- Websocket
三、 架構
我們Nginx來代理3個web應用服務器。3臺web應用服務器上部署的web應用實現了打開首頁分別創建一個websocket鏈接,並能夠接收自己的上下線信息,通知其他用戶自己的上下線狀態。以及實現給其他客戶端發送消息的功能。
爲了解決websocket會話不在同一臺服務上的問題。我們來使用Kafka來做消息中間件。Kafka是一個由Zookeeper來調度的,分佈式高可用消息中間件。
這裏說明一下Kafka的消息消費的原理。本質上Kafka只支持Topic.每個consumer屬於一個consumer group;反過來說,每個group中可以有多個consumer.發送到Topic的消息,只會被訂閱此Topic的每個group中的一個consumer消費。
我們的web應用服務器上實現了多個消息生產者,產生的消息放在同一chattopic
topic下,每一個web應用上的消費者爲一個組。這樣,我們將產生的消息全部放入到一個topic下,3個web應用服務器上的消費者,由於屬於不同的消費組,所以每web應用服務器都能獲得所有消息。當web應用服務器上的消費者獲得一個消息時,通過消息中接收客戶端的id,可以判斷實際接收的客戶端的websocket會話是否在本地,如果不在本地就將消息放棄掉,如果在本地那麼就將消息通過session會話推送出去。
四、 開發環境搭建
建議調試和開發工具使用IDEA。
使用Docker搭建Zookeeper和Kafka
該環境的docker-compose.yml文件路徑:/dockerWeb/webapp/docker/dev-zk-kafka/docker-compose.yml
。
其中如下代碼,配置了子網。其實可以不用配置子網,並指定服務ip地址。只要我們的zookeeper和kafka的配置文件中,均使用services
的名稱(hostname)即可。
注意:
我們需要在開發環境的系統中將hosts文件中添加如下映射
127.0.0.1 zookeeper-1
127.0.0.1 zookeeper-2
127.0.0.1 zookeeper-3
127.0.0.1 kafka-1
127.0.0.1 kafka-2
127.0.0.1 kafka-3
我們運行如下命令,即可啓動開發環境的Zookeeper和Kafka了。
docker-compose up
啓動完畢後,我們可以通過idea的調試工具,調試Spring-boot的啓動文件DockerWebApp.java
。
然後我們在瀏覽器中訪問http://localhost:8080/
,看到如下界面:
五、正式測試環境
正式測試環境的配置文件路徑是/dockerWeb/webapp/docker/docker-compose.yml
。在項目根目錄下運行mvn clean install
命令後,再到/dockerWeb/webapp/docker/
下運行docker-compose up
啓動測試環境。
然後我們在瀏覽器中訪問http://localhost:8080/
,看到如下界面: