摘要:唯一的知識點就是的基礎使用。可以簡單的理解下面的代碼就構建了一個服務器。握手完成之后的消息傳遞則在中處理。實際情況下,不可能那么多人同時說話廣播,而是說話的人少,接受廣播的人多。
硬廣一波
SF 官方首頁推薦《PHP進階之路》(你又多久沒有投資自己了?先看后買)
我們下面則將一些實際場景都添加進去,比如用戶身份的驗證,游客只能瀏覽不能發言,多房間(頻道)的聊天。
該博客非常適合 Java 新手,非常適合作為學習 Java 的切入點,不需要考慮tomcat、spring、mybatis等。
唯一的知識點就是 maven 的基礎使用。
https://github.com/zhoumengka...
├── WebSocketServer.java 啟動服務器端口監聽 ├── WebSocketServerInitializer.java 初始化服務 ├── WebSocketServerHandler.java 接管WebSocket數據連接 ├── dto │ └── Response.java 返回給客戶端數據對象 ├── entity │ └── Client.java 每個連接到WebSocket服務的客戶端對象 └── service ├── MessageService.java 完成發送消息 └── RequestService.java WebSocket初始化連接握手時的數據處理功能設計概述 身份認證
客戶端將用戶 id 、進入的房間的 rid、用戶 token json_encode,例如{id:1;rid:21;token:"43606811c7305ccc6abb2be116579bfd"}。然后在 base64 處理,通過參數request傳到服務器,然后在服務器做 id 和 token 的驗證(我的做法是 token 存放在redis string 5秒的過期時間)
房間表使用一個Map channelGroupMap 來存放各個房間(頻道),以客戶端傳握手時傳過來的 base64 字符串中獲取到定義的房間 ID,然后為該房間 ID 新建一個ChannelGroup(ChannelGroup 方便對該組內的所有客戶端廣播消息)
在 pom.xml 中引入netty 5現在大家都有自己的包管理工具,不需要實現下載了然后放到本地lib庫中,和 nodejs 的 npm, php 的 compser 一樣。
創建服務器io.netty netty-all 5.0.0.Alpha2 com.jcraft jzlib 1.1.2 org.json json 20141113 commons-codec commons-codec 1.10
這段代碼需要理解嗎?這是 netty 的套路,可以先記住 netty 的線程模型是一個 react 的一種變型,這里有兩個nio線程組,一個是接受客戶端的請求,一個是worker組專門處理客戶端的請求。
可以簡單的理解下面的代碼就構建了一個nginx服務器。所以不用管。
package net.mengkang; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public final class WebSocketServer { private static final int PORT = 8083; public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new WebSocketServerInitializer()); Channel ch = b.bind(PORT).sync().channel(); ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
package net.mengkang; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; public class WebSocketServerInitializer extends ChannelInitializer處理長連接{ @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new WebSocketServerCompressionHandler()); pipeline.addLast(new WebSocketServerHandler()); } }
下面程序中最的處理在握手階段handleHttpRequest,里面處理參數的判斷,用戶的認證,登錄用戶表的維護,直播房間表維護。詳細的請大家對照代碼來瀏覽。
握手完成之后的消息傳遞則在handleWebSocketFrame中處理。
整理的執行流程,大家可以對各個方法打斷點予以調試,就會很清楚整個執行的脈絡啦。
package net.mengkang; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.handler.codec.http.*; import io.netty.handler.codec.http.websocketx.*; import io.netty.util.CharsetUtil; import io.netty.util.concurrent.GlobalEventExecutor; import net.mengkang.dto.Response; import net.mengkang.entity.Client; import net.mengkang.service.MessageService; import net.mengkang.service.RequestService; import org.json.JSONObject; import java.util.HashMap; import java.util.List; import java.util.Map; import static io.netty.handler.codec.http.HttpHeaderNames.HOST; import static io.netty.handler.codec.http.HttpMethod.GET; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; public class WebSocketServerHandler extends SimpleChannelInboundHandler
服務器端就寫完啦,還有一些客戶端對象的構想驗證什么的就不一一細說了,都很簡單,都在代碼里。下面是客戶端。
客戶端程序并發壓測
同事 https://github.com/ideal 寫的壓測腳本
https://github.com/zhoumengka...
并測試為N個客戶端,每個客戶端發送10條消息,服務器配置2核4G內存,廣播給所有的客戶端,我們測試1500個并發的時候,負載在后期陡升。
實際情況下,不可能那么多人同時說話廣播,而是說話的人少,接受廣播的人多。
實際線上之后(業務遠比上面的代碼負載得多的多),在不限制刷帖頻率大家狂轟濫炸的情況下,1500多人在線,半小時,負載一直都處于0.5以下。
最近老鐵開了直播,歡迎來捧場!PHP 進階之路 - 億級 pv 網站架構的技術細節與套路
PHP 進階之路 - 億級 pv 網站架構實戰之性能壓榨
PHP 進階之路 - 后端多元化之快速切入 Java 開發
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67319.html
摘要:最近在維護一個三年前的舊代碼,用的是框架。單元測試和語言并發控制實際上是個蛋疼的問題,夸張一點說,當時的并不能特別輕松地實現并發,甚至不能實現并發。語言的功能之一就是自帶單元測試。用語言之前,我的習慣是不寫單元測試。 最近在維護一個三年前的舊代碼,用的是laravel框架。 從某些方面來講,這個代碼算是比較標準為了實現在規定的時間內完成相關功能,同時程序員水平不高、經過大量優化之后,變...
摘要:項目介紹是一個全新的語言的運行時環境,基于目前最新的進行打造,支持最新的語言規范,同時提供了自己的運行時標準庫。同樣也在的基礎上進行打造,實現了一個除開發之外的一個全新的運行環境。發布核心虛擬機的鏡像。整合運行時框架。 showImg(https://segmentfault.com/img/bVbnQXK); polarphp 項目介紹 polarphp是一個全新的PHP語言的運行時...
摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...
摘要:行爬取頂點全網任意小說掘金之前連續多篇文章介紹客戶端爬取平臺,今天我們從零開始,實現爬取頂點小說網任意一本小說的功能。文件標記所有文件我的后端書架后端掘金我的后端書架月前本書架主要針對后端開發與架構。 30行js爬取頂點全網任意小說 - 掘金之前連續多篇文章介紹客戶端爬取平臺(dspider),今天我們從零開始,實現爬取頂點小說網任意一本小說的功能。 如果你還不知道客戶端爬取,可以先看...
閱讀 3596·2020-12-03 17:42
閱讀 2768·2019-08-30 15:54
閱讀 2222·2019-08-30 15:44
閱讀 570·2019-08-30 14:08
閱讀 969·2019-08-30 14:00
閱讀 1102·2019-08-30 13:46
閱讀 2784·2019-08-29 18:33
閱讀 2885·2019-08-29 14:11