网络聊天室项目介绍
文章目錄
- 項目介紹
- 項目地址
- 項目底層核心運行架構
- 版本1
- 版本2
- BUG記錄
- 后續計劃
項目介紹
本項目主要是開發一個網絡傳輸中間組件,實現1對1和1對多的網絡通信,并且有效解決一些常用的丟包和粘包的問題。目前支持超大文件傳輸。
主要應用場景:如網絡聊天室,當然可以擴展應用
開發語言:Java
涉及技術:NIO,高并發.
項目地址
https://github.com/13days/socket-learn
當前版本在socket-learn/chatRoom_1_0/這個目錄下維護。
項目底層核心運行架構
版本1
核心連接器,包括發送和接收兩部分,值得一提的是,發送和接收都是支持并發的。在發送字符串的時候我們把他封裝成一個包再拆分發送到網絡。
并發調度結構入下:
在這個版本中,對于每一個客戶端/或服務端。他的接收和發送都必須連接到一個IoProvider的調度器上面。在調度器上面分別由讀線程和寫線程來分派任務,其中讀線程監聽,寫線程發送。所有的任務都會委派到線程池中取完成,最后完成時收到回調通知,重寫組織數據。并返回業務層做相應的處理。
發送執行調度流程如下:
其中SendDispatcher的兩條路徑分別是發送完一個Packet和繼續發送當前Packet的兩條路徑。
版本2
在這個版本中提供了更良好的代碼封裝。引入了3重緩沖機制,支持超大文件發送,并做了壓測,支持20WBPS,在此規模下,jvm消耗內存僅由100M左右,并且支持更多的長連接數,在壓測版本中,可能同時支持10w長連接,當然,連接量還和并發發送的頻率有關,此消彼長。
運行數據流圖大致情況
在這里面你會看到上個版本沒有的東西,比如Frame幀的概念,比如Channel通道的概念。這是引入了3級緩沖所帶了的新實體。
為什么要引入3級緩沖呢?
當需要發送的數據量過大的時候,我們總不可能期望把數據都讀到內存里然后再進行發送,這樣服務器內存會飆升的!!!
所以我們引入了第一級緩沖,Channel通道的方式,和上個版本保存一致的是,上個版本的數據讀到Packet里,而這個版本Packet里面實際存放的是Channel。
當數據讀到Channel里面后,我們就和可以分批次去讀數據啦!當時還有兩個問題,讀多少數據進來呢?讀到的數據如何保證有序呢?這就引入了第2級緩沖。
在這里緩沖里我們定義了實體幀Frame(后面你會看到具體的數據結構),每個幀由首部和實體構成,根據首部我們可以構建完整的數據,這不僅解決了順序問題,還解決了消息粘包的問題!當然,我們不可能一次讀很少的數據發送到網絡中去,這樣會發送很多次本地的IO,大大降低了程序的執行速率,但是,我們又不能一次把讀到的數據發送到網絡中去,這樣發送的數據過多,會大大減少并發量。
所以針對這個問題,我們采用了第3級緩沖,IoArgs,這是具體發送到網絡中的數據,多個IoArgs組成一個Frame,IoArgs的大小可以根據實際環境進行配置。
這樣做的好處在哪呢?
這樣能做到持久層內存>>運行內存>單次網絡數據量
使得,并發量大大提升,網絡被充分利用,增加了服務器的穩定性,多條數據真正并發發送
三級緩沖的數據結構
Chanel = Frame+Frame+Frame…
Frame = (報文+實體) = IoArgs+IoArgs+IoArgs…
下面的內容是介紹一下程序運行時的數據流圖
在上面的發送流圖中,我們可以看到大量使用了回調功能,比如回調發送下一個IoArgs,或者構建下一個Frame或則回調到上層發送異常或者回調通知上層應用完成處理等。
接送數據的執行流圖‘
在TCP完成監聽之后的回調任務如下
上面是一個線程在監聽到有任務到達的回調,通過幀的ID來構建發送方發送過來的幀,在組裝成包的形式提供給應用層使用。
BUG記錄
主要是空指針buff,如連接斷開促發。還有selectionkey沒有即使注銷掉的問題,導致其他鏈接無法使用。
后續計劃
后續打算擴展業務層相關的功能。
總結
- 上一篇: 解决Spring文件下载时文件损毁问题
- 下一篇: PUN☀️七、网络同步:Object S