項目總結:近期的兩個小項目

本文同時發(fā)布至我的個人博客空另,點擊進入我的個人博客閱讀。本博客供技術交流與經驗分享蹋砚,可自由轉載扼菠。轉載請在評論區(qū)或私信簡單通知摄杂,感謝!
近期為了應對校招面試循榆,比較有針對性地做了兩個技術項目:一個是基于 Java NIO 實現(xiàn)的簡易版非阻塞 Http 服務器匙姜,另一個是基于 Spring Boot + Websocket 實現(xiàn)的網絡聊天室。與以往的項目總結不同冯痢,這次我會忽略一些代碼實現(xiàn)細節(jié),把更多的篇幅用來總結開發(fā)過程中我遇到的難題以及在面試中面試官提出的相關問題框杜。

基于 Java NIO 實現(xiàn)的簡易版非阻塞 Http 服務器

首先需要強調的是浦楣,這種 Http 服務器的實現(xiàn)是非常樸素直接的,沒有考慮很多具體實踐中的問題咪辱。最近在看《Netty In Action》才越來越感覺之前做項目時想法上的過于單純振劳。但項目本身其實十分適合初學者進階的,因為其中涉及到的知識:Java NIO油狂、網絡多路復用历恐、Http 報文解析、緩沖區(qū)設計专筷,都是十分重要的基礎問題弱贼,也是在校招技術面試中面試官喜歡深入考察的問題。在開發(fā)過程中磷蛹,我借鑒了 Java NIO: Non-blocking Server非阻塞服務器這篇文章的思路吮旅,上面提及的幾個關鍵問題文章中也有較為詳細的解析。

項目基本架構

image

Java BIO/NIO/AIO

關于 Java BIO/NIO/AIO 這三者的區(qū)別味咳,個人覺得 Java BIO, NIO, AIO understanding 這篇文章總結得十分簡潔到位庇勃,作者分別從編程、原理槽驶、底層三方面進行總結责嚷。編程方面作者講解的十分到位,而要理解原理部分可能需要一些 Unix 網絡編程的相關知識掂铐,以下就做一些網絡編程相關的補充:

  • Unix 網絡編程中將 IO 模型分為五類:阻塞 IO罕拂、非阻塞 IO(輪詢)、IO 復用堡纬、信號驅動式 IO聂受、異步 IO。其中非阻塞 IO(輪詢)烤镐、IO 復用蛋济、信號驅動式 IO 都可以理解為非阻塞 IO 的不同形式實現(xiàn)。(圖解UNIX的I/O模型一文可以讓你快速理解 Unix 中的 IO 模型)

  • 無論是屬于哪種 IO 模型炮叶,其 IO 過程都可以分為兩個階段: IO request(數(shù)據(jù)請求)和 IO operation(數(shù)據(jù)復制)兩個階段碗旅。

  • 阻塞 IO 與非阻塞 IO 的區(qū)別在于:使用阻塞 IO 時渡处,線程在 IO request 和 IO operation 階段都會進入阻塞;而使用非阻塞 IO 時祟辟,線程只在 IO operation 階段進入阻塞医瘫,IO request 無需阻塞。

  • 同步 IO 與異步 IO 的區(qū)別在于:同步 IO 在 IO operation 階段會進入阻塞旧困,而異步 IO 在 IO request 和 IO operation 階段都不會進入阻塞醇份。

  • 按照 Unix 網絡編程中對 IO 模型的分類,Java BIO/NIO/AIO 的實現(xiàn)分別對應了阻塞 IO/IO 多路復用/異步 IO 這三種模型吼具。

BIO vs NIO

Java AIO(在 JDK 1.7 中也稱為 NIO.2)僚纷,在性能上相較于 NIO 并沒有帶來提升,所以在 Netty 4.0.0 中也移除了對 AIO 的支持拗盒。無論是在實際應用中還是在技術面試中都較少提及 AIO怖竭,這里我們重點比較一下 BIO 與 NIO 的區(qū)別:

  1. 處理的對象:BIO 直接面向 Socket 的字節(jié)流,每次從流中讀一個或多個字節(jié)陡蝇,直到讀取完所有字節(jié)痊臭;NIO 面向緩沖塊(Block),需要時可以在緩沖區(qū)中前后移動處理登夫,這增加了處理過程的靈活性广匙。

  2. 阻塞:BIO 必須要對線程進行阻塞,NIO 無需阻塞悼嫉,一個單獨的線程可以管理多個輸入和輸出通道艇潭。

  3. 選擇器:Java NIO的選擇器允許一個單獨的線程同時監(jiān)視多個通道,可以注冊多個通道到同一個選擇器上戏蔑,然后使用一個單獨的線程來“選擇”已經就緒的通道蹋凝。

  4. 零拷貝:Java NIO中提供的 FileChannel 擁有 transferTotransferFrom 兩個方法,可直接把 FileChannel 中的數(shù)據(jù)拷貝到另外一個 Channel总棵,或者直接把另外一個 Channel 中的數(shù)據(jù)拷貝到 FileChannel 鳍寂。通過該方法傳輸數(shù)據(jù)并不需要將源數(shù)據(jù)從內核態(tài)拷貝到用戶態(tài),再從用戶態(tài)拷貝到目標通道的內核態(tài)情龄,同時也避免了兩次用戶態(tài)和內核態(tài)間的上下文切換迄汛,也即使用了“零拷貝”。

總結自:Java進階(五)Java I/O模型從 BIO到 NIO和 Reactor模式

HTTP 報文及解析

項目中對 HTTP 協(xié)議的支持也做了簡化處理:只判別了 GET骤视、POST鞍爱、HEAD、PUT专酗、DELETE 五種方法睹逃,主要是基于 HTTP 的 Content-Length 字段來實現(xiàn) HTTP 報文切割(處理 TCP 粘包問題)。但是在面試中,HTTP 協(xié)議幾乎是所有面試官會深究的一部分內容沉填。大概涉及的問題如下:

Message 緩沖區(qū)設計

  • 讀取不完整的 message:每次 Reader 從 Channel 讀取一個數(shù)據(jù)塊后,先通過一個 Http 報文 parser 來確定是否有一個完整的 message猎荠。若有坚弱,則讀取一個完整的 message 后將剩余部分緩存起來;若無关摇,則直接將整個數(shù)據(jù)塊緩存起來史汗。緩存的數(shù)據(jù)塊將在下次讀取時與下次讀取的數(shù)據(jù)塊合并,再進行重新的 parsing拒垃。

  • message buffer 的大小:MessageBuffer 實現(xiàn)了一個容量可伸縮的 message buffer瓷蛙。它提供三種大小的 buffer悼瓮,4KB/128KB/1MB。初始時 buffer 默認為 4KB艰猬,若空間不足時横堡,MessageBuffer 內部的方法會自動將 buffer 擴容。

  • message buffer 的讀寫:仿寫了 nio.Buffer 中的 flip() 函數(shù)(readPoswritePos)冠桃,在 message buffer 的讀寫操作中調用 flip() 來避免錯讀命贴、漏讀。

生產者-消費者隊列

用一個 ArrayBlockingQueue 來存放 socket食听,創(chuàng)建兩個線程胸蛛,acceptor 和 processor 分別使用其 put / take 操作來進行生產和消費。

關于 ArrayBlockingQueue:1. 基于數(shù)組樱报,直接將對象放入和取出隊列葬项。(LinkedBlockingQueue 基于單向鏈表,放入與取出時操作 Node)迹蛤;2. 基于一個 ReentrantLock 和兩個 Condition(notEmpty 和 notFull) 實現(xiàn)民珍。(LinkedBlockingQueue 基于兩個 ReentrantLock :putLock 和 takeLock 和兩個 Condition:notEmpty 和 notFull 實現(xiàn))

基于 Spring Boot + Websocket 實現(xiàn)的網絡聊天室

項目實現(xiàn)了一個簡單的網絡聊天室,基于 Spring Boot 搭建后臺盗飒,基于 Websocket 與 STOMP 協(xié)議實現(xiàn)即時通訊嚷量,使用 Spring Security 與 Spring Oauth 實現(xiàn)用戶登錄,基于 JWT 實現(xiàn)對單點登錄的支持逆趣。

Oauth 驗證流程

image

Websocket 協(xié)議

參考WebSocket協(xié)議深入探究

JWT

  • JWT(Json Web Token) 一個非常輕巧的規(guī)范蝶溶。這個規(guī)范允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。

  • 字符串形式汗贫,三部分組成:頭部(Header)身坐、載荷(Payload)秸脱、簽名(Signature)

  • 頭部:用于描述 JWT

    
    {
    
      "typ": "JWT",
    
      "alg": "HS256" // 指定簽名的加密算法
    
    }
    
    
  • 載荷:真正需要傳遞的內容 + 部分其他信息

    
    {
    
        "iss": "User JWT",
    
        "iat": 1441593502,
    
        "exp": 1441594722,
    
        "aud": "www.example.com",
    
        "sub": "sub@example.com",
    
        "from_user": "B",
    
        "target_user": "A"
    
    }
    
    
  • 簽名:用于在服務端判斷 JWT 的內容是否經過篡改,使用 JWT 頭部指定的加密算法部蛇。

  • 格式:header.payload.signature(先通過 base64 將 JSON 轉化為字符串)

  • 載荷內容可以通過 base64 反編碼獲得摊唇,所以不應用 JWT 傳輸敏感數(shù)據(jù)。

  • 使用場景:添加好友涯鲁、創(chuàng)建訂單巷查、實現(xiàn)單點登錄

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市抹腿,隨后出現(xiàn)的幾起案子岛请,更是在濱河造成了極大的恐慌,老刑警劉巖警绩,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崇败,死亡現(xiàn)場離奇詭異,居然都是意外死亡肩祥,警方通過查閱死者的電腦和手機后室,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來混狠,“玉大人岸霹,你說我怎么就攤上這事〗龋” “怎么了贡避?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長予弧。 經常有香客問我刮吧,道長,這世上最難降的妖魔是什么掖蛤? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任皇筛,我火速辦了婚禮,結果婚禮上坠七,老公的妹妹穿的比我還像新娘水醋。我一直安慰自己,他們只是感情好彪置,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布拄踪。 她就那樣靜靜地躺著,像睡著了一般拳魁。 火紅的嫁衣襯著肌膚如雪惶桐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機與錄音姚糊,去河邊找鬼贿衍。 笑死,一個胖子當著我的面吹牛救恨,可吹牛的內容都是我干的贸辈。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼肠槽,長吁一口氣:“原來是場噩夢啊……” “哼擎淤!你這毒婦竟也來了?” 一聲冷哼從身側響起秸仙,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤嘴拢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寂纪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體席吴,經...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年捞蛋,在試婚紗的時候發(fā)現(xiàn)自己被綠了抢腐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡襟交,死狀恐怖,靈堂內的尸體忽然破棺而出伤靠,到底是詐尸還是另有隱情捣域,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布宴合,位于F島的核電站焕梅,受9級特大地震影響,放射性物質發(fā)生泄漏卦洽。R本人自食惡果不足惜贞言,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阀蒂。 院中可真熱鬧该窗,春花似錦、人聲如沸蚤霞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昧绣。三九已至规肴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拖刃。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工删壮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兑牡。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓央碟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親发绢。 傳聞我的和親對象是個殘疾皇子硬耍,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內容