三分鍾構建高性能WebSocket服務 | 超優雅的Springboot整合Netty方案


前言

每當使用SpringBoot進行Weboscket開發時,最容易想到的就是spring-boot-starter-websocket(或spring-websocket)。它可以讓我們使用注解,很簡單的進行Websocket開發,讓我們更多的關注業務邏輯。它底層使用的是Tomcat,且不說把整個Tomcat放進一個WebSocket服務中是否會太重,但在大數據量高並發的場景下,它的表現並不是非常理想。

Netty一款高性能的NIO網絡編程框架,在推送量激增時,表現依然出色。(關於性能與表現的討論,網上很多,這里不過多說明。)很多流行開源項目都在使用Netty,如:Dubbo、Storm、Spark、Elasticsearch、Apache Cassandra等,這得益於Netty的並發高、傳輸快、封裝好等特點。

但是,要在SpringBoot項目中整合Netty來開發WebSocket不是一件舒服的事,這會讓你過多的關注非業務邏輯的實現。那么,是否有一款框架,能使得在SpringBoot項目中使用Netty開發WebSocket變得簡單,甚至優雅,並且可以從使用spring-boot-starter-websocket開發的項目無縫的遷移過來呢?

netty-websocket-spring-boot-starter

這是個開源的框架。通過它,我們可以像spring-boot-starter-websocket一樣使用注解進行開發,只需關注需要的事件(如OnMessage)。並且底層是使用Netty,當需要調參的時候只需要修改配置參數即可,無需過多的關心handler的設置。

快速入門

  • 創建SpringBoot項目(v2.0.0以上)並添加依賴:
	<dependency>
		<groupId>org.yeauty</groupId>
		<artifactId>netty-websocket-spring-boot-starter</artifactId>
		<version>0.6.3</version>
	</dependency>
  • new一個ServerEndpointExporter對象,交給Spring容器,表示要開啟WebSocket功能:
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
  • 在端點類上加上@ServerEndpoint@Component注解,並在相應的方法上加上@OnOpen@OnClose@OnError@OnMessage注解(不想關注某個事件可不添加對應的注解):
@ServerEndpoint
@Component
public class MyWebSocket {

    @OnOpen
    public void onOpen(Session session, HttpHeaders headers) throws IOException {
        System.out.println("new connection");
    }

    @OnClose
    public void onClose(Session session) throws IOException {
       System.out.println("one connection closed"); 
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnMessage
    public void OnMessage(Session session, String message) {
        System.out.println(message);
        session.sendText("Hello Netty!");
    }
}

  • 一個高性能的WebSocket服務端就完成了,直接run起來就可以了。

測試

  • 服務端是寫完了,接下來需要測試一下,看看效果
  • 首先,新建一個html文件,把頁面擼出來
<!DOCTYPE html>
<html lang="en">
<body>
<div id="msg"></div>
<input type="text" id="text">
<input type="submit" value="send" onclick="send()">
</body>
<script>
    var msg = document.getElementById("msg");
    var wsServer = 'ws://127.0.0.1:80';
    var websocket = new WebSocket(wsServer);
    //監聽連接打開
    websocket.onopen = function (evt) {
        msg.innerHTML = "The connection is open";
    };

    //監聽服務器數據推送
    websocket.onmessage = function (evt) {
        msg.innerHTML += "<br>" + evt.data;
    };

    //監聽連接關閉
    websocket.onclose = function (evt) {
        alert("連接關閉");
    };

    function send() {
        var text = document.getElementById("text").value
        websocket.send(text);
    }
</script>
</html>
  • 頁面擼完,直接用Chrome打開上面html文件即可連上你的WebSocket服務。

總結

這個框架是基於Netty的,所以直接使用Netty優化時的理念即可。如:堆外內存的0拷貝、接收及發送緩沖區的調整、高低寫水位的調整等。

生產環境的項目在充分調優后,Netty甚至能比Tomcat高效20倍。(當然,這是特定的場景下)

框架詳細文檔:https://github.com/YeautyYE/netty-websocket-spring-boot-starter


免責聲明!

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



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