乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      帶你手?jǐn)]一個(gè)http服務(wù)器(帶源碼)

       flyk0tcfb46p9f 2019-05-13

      作為一個(gè)程序猿,對造輪子這事情可以說是情有獨(dú)鐘,幾乎程序猿內(nèi)心都存在一個(gè)夢想是去將開源的技術(shù)都實(shí)現(xiàn)一遍,所有從本篇開始,我會(huì)開一個(gè)造輪子系列。


      前言

      首先,看看這個(gè),想必大家對下面這種簡歷看得比較多了吧?

      • 精通JAVA,Python,熟練掌握C++

      • 精通Redis,Memcached,Mysql

      • 精通Nginx配置,模塊開發(fā)

      • 精通Kafka,ActiveMQ 等消息隊(duì)列

      • 精通常用數(shù)據(jù)結(jié)構(gòu)和算法

      • 精通網(wǎng)絡(luò)編程,多線程編程技術(shù),高性能服務(wù)器技術(shù)

      • 精通tcp/ip協(xié)議棧,熟悉內(nèi)核網(wǎng)絡(luò)子系統(tǒng)代碼

      • 精通nginx代碼及模塊開發(fā)

      上面每一條都涉及好多輪子,每一個(gè)都是精通,如果真能做到。那這個(gè)人可以說是碼農(nóng)中的戰(zhàn)斗機(jī)。

      那我們現(xiàn)在目標(biāo)就是去做這個(gè)戰(zhàn)斗機(jī)。而這個(gè)方法,就是自己去造輪子,造的目的不是為了在項(xiàng)目中使用自己造的輪子,而是為了去了解輪子的構(gòu)造,然后自己動(dòng)手去體會(huì)造輪子的過程。


      后端的輪子們

      說起后端的輪子們,大家都可以說出一大串來,我們大致來數(shù)一數(shù)啊。

      • 抗在最前面的:LVS,F(xiàn)5,HAProxy這類負(fù)載均衡

      • 接下來有Nginx,Apache,Lighttpd這類Http服務(wù)

      • http服務(wù)后則是各種容器,部署著我們的業(yè)務(wù)邏輯

      • 存儲(chǔ)這邊有Redis,Memcached這一類KV存儲(chǔ)器和緩存系統(tǒng)

      • 如果是多機(jī)部署,肯定還有Kafka,ActiveMQ這種負(fù)責(zé)解耦的消息隊(duì)列

      • 為了實(shí)現(xiàn)集群通信,肯定少不了Thrift這種RPC框架和Protobuf這種序列化技術(shù)

      • 再高端點(diǎn),到了分布式領(lǐng)域了,就是更多的輪子了。。zookeeper、raft等等

      • 還有大數(shù)據(jù)系列hadoop。spark。。。。。

      本文主要講http協(xié)議。

      正文分割線


      我們都知道http是基于tcp之上的,那我們現(xiàn)在就自己基于tcp來實(shí)現(xiàn)一個(gè)最小的http服務(wù),功能非常簡單:

      • 返回輸入?yún)?shù)

      先來看請求格式:

      http的報(bào)文大概分為3部分:

      • 請求行

      • 首部

      • 正文部分

      此處請求行是格式是固定的,

      先寫代碼來看看的:

      可以看到我們讀取的到數(shù)據(jù)是如上,我們可以看到格式上是符合的。

      Ps:上面這個(gè)代碼有個(gè)小問題,因?yàn)閠cp連接是字節(jié)流的,我們通過readAll方法從連接中讀取數(shù)據(jù)的是,只要瀏覽器上不主動(dòng)斷開,會(huì)一直阻塞在readaALL上。。。

      上面我們將收到的數(shù)據(jù)稍微整理下

      • 請求行

      • POST / HPPP/1.1\r\n

      • 格式:方法 space URL space 版本 cr lf

      • 首部

      • Host: 127.0.0.1:8080

      • Content-length: 0

      • 格式:首部字段名 space 字段值 cr lf

      • 正文部分

      • 此處為空

      上面首部中Content-length: 0可以說是非常關(guān)鍵,他告訴了我們應(yīng)該要在兩個(gè)\r\n后繼續(xù)讀取多少字節(jié)。

      下面我們開始來寫解析代碼,先是解析文件頭

      然后我們再解析首部

      解析完后,我們在寫返回值,返回報(bào)文的格式放下:

      下面是返回值的代碼:

      完整的例子可以看GitHub上代碼,歡迎star

      https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/http/v1

      我們有了第一版http輪子后,我們能和前面介紹的輪子系列:rpc聯(lián)系起來,在rpc系列中,我們講了設(shè)計(jì)通信協(xié)議來傳遞消息,此處http是通過頭部的url+method的方法來表示我要調(diào)用服務(wù)端哪個(gè)方法,然后分割符是使用 \r\n,連續(xù)兩個(gè)\r\n表示后續(xù)是消息體,為了高速我們消息體的大小和格式,在header中必須指明content-type和content-length,這些都是在我們在實(shí)現(xiàn)http協(xié)議的時(shí)候遵循的。

      那現(xiàn)在寫完最初版代碼,我們回過頭總結(jié)下我們之前做的rpc輪子,數(shù)據(jù)編碼采用了protobuf,然后基于tcp自己定義了一套消息協(xié)議,其實(shí)做的事情跟http/1.1是一樣的,我們完全可以在http通信的時(shí)候,將content-type設(shè)置為protobuf,然后通信雙方雙方能夠編解碼即可。

      在實(shí)現(xiàn)過程中,我們發(fā)現(xiàn)如果用http1.1作為通信協(xié)議,有什么問題呢?

      1. 每次傳輸都要完整的http頭,浪費(fèi)帶寬

      2. 每次一個(gè)http請求,一個(gè)request,response都要獨(dú)占一條tcp連接,不然不知道response對應(yīng)哪個(gè)request,影響實(shí)時(shí)性和并發(fā)性

      那上面這兩點(diǎn)都是要解決的問題,在http2.0中都有相應(yīng)的方案

      1. 針對每次都需要傳輸http頭,通信雙方建立索引,后續(xù)傳輸只用索引

      2. 針對連接占用,一條連接只能同時(shí)有一個(gè)請求-響應(yīng),http2.0啟動(dòng)了多路復(fù)用,即允許一個(gè)連接同時(shí)發(fā)起多個(gè)請求

      那怎么能做到一個(gè)連接同時(shí)發(fā)起多個(gè)請求呢?通信雙方就必須對每個(gè)請求進(jìn)行編碼,這樣不同的響應(yīng)就能和請求對應(yīng)上了。

      具體可以看兩張圖:

      HTTP 2.0 其實(shí)是將三個(gè)請求變成三個(gè)流,將數(shù)據(jù)分成幀,亂序發(fā)送到一個(gè)tcp連接中

      通過stream對不同請求進(jìn)行區(qū)分,然后在將一個(gè)消息拆分為多個(gè)幀進(jìn)行發(fā)送。

      那http2.0后,還能不能更快了呢?于是就有了QUIC協(xié)議,這個(gè)協(xié)議肯定是為了解決http2.0的某些問題的。

      1. 自定義連接機(jī)制:tcp連接三次握手慢,由于在移動(dòng)端,由于網(wǎng)絡(luò)從wifi到移動(dòng)網(wǎng)絡(luò)切換時(shí),必定會(huì)導(dǎo)致連接斷開重連,再次需要3次握手,那我們就自定義連接機(jī)制,原先tcp一條連接是由4元素組成:分別是源 IP、源端口、目的 IP、目的端口,現(xiàn)在以一個(gè)64位隨機(jī)數(shù)來作為連接標(biāo)志,斷開了也沒事,重新建立連接不需要3次握手了。

      2. 自定義重傳機(jī)制:tcp是可靠連接,當(dāng)前面的數(shù)據(jù)編號沒有收到的時(shí)候,后面的數(shù)據(jù)即使收到了,也不會(huì)得到確認(rèn),這就必須要重傳

      重傳有個(gè)測不準(zhǔn)問題,左邊是1.1,我們發(fā)現(xiàn)重發(fā)100編號的時(shí)候,如果后續(xù)收到應(yīng)答101,我們不知道這個(gè)是針對第一次100的應(yīng)答還是第二次重傳100的應(yīng)答,http2.0則定義了每次發(fā)送數(shù)據(jù),編號都需要增加,然后通過offset來標(biāo)明數(shù)據(jù)的前后續(xù)關(guān)系。

      1. 無阻塞多路復(fù)用:因?yàn)閠cp是面向字節(jié)流的可靠連接,所以數(shù)據(jù)之間是有依賴的,因此為了減少依賴,讓不同流之間真的能夠獨(dú)立,可以采用udp

      2. 自定義流量控制:tcp的流量控制是通過滑動(dòng)窗口協(xié)議,udp也是滑動(dòng)窗口,而且是每個(gè)stream都有自己的窗口。

      總結(jié)

      首先本文基于tcp自己實(shí)現(xiàn)了http1.1的協(xié)議,實(shí)現(xiàn)中發(fā)現(xiàn)這個(gè)通信協(xié)議和我們之前輪子系列文章rpc都是消息協(xié)議,只是對消息體的編碼格式不同而已。

      接著我們在自己寫的過程中發(fā)現(xiàn)了http1.1的種種問題,針對這些問題有了http2.0,繼而又有了QUIC。

      預(yù)告:今天講完http2.0后,我會(huì)接著講輪子系列:gRpc,這個(gè)通信協(xié)議使用就是http2.0,歡迎大家關(guān)注。

      Ps:文章最后關(guān)于http2.0和quic的內(nèi)容主要來自極客時(shí)間的趣談網(wǎng)絡(luò)協(xié)議,寫的真的非常好,大家可以去訂閱的,當(dāng)然通過我的邀請碼可以有返現(xiàn)的,歡迎加wx: hithangtian

      源碼地址:https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/http/v1

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多