1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        websocket 實現(xiàn)長連接原理

        共 8468字,需瀏覽 17分鐘

         ·

        2021-05-19 02:37

        點擊上方藍色字體,選擇“標星公眾號”

        優(yōu)質文章,第一時間送達

          作者 |  大礙桃花開 

        來源 |  urlify.cn/j2UFfa

        一、WebSocket是HTML5出的東西(協(xié)議),也就是說HTTP協(xié)議沒有變化,或者說沒關系,但HTTP是不支持持久連接的(長連接,循環(huán)連接的不算)首先HTTP有1.1和1.0之說,也就是所謂的keep-alive,把多個HTTP請求合并為一個,但是Websocket其實是一個新協(xié)議,跟HTTP協(xié)議基本沒有關系,只是為了兼容現(xiàn)有瀏覽器的握手規(guī)范而已,也就是說它是HTTP協(xié)議上的一種補充可以通過這樣一張圖理解

        有交集,但是并不是全部。
        另外Html5是指的一系列新的API,或者說新規(guī)范,新技術。Http協(xié)議本身只有1.0和1.1,而且跟Html本身沒有直接關系。。
        通俗來說,你可以用HTTP協(xié)議傳輸非Html數(shù)據(jù),就是這樣=。=
        再簡單來說,層級不一樣。


        二、Websocket是什么樣的協(xié)議,具體有什么優(yōu)點
        首先,Websocket是一個持久化的協(xié)議,相對于HTTP這種非持久的協(xié)議來說。
        簡單的舉個例子吧,用目前應用比較廣泛的PHP生命周期來解釋。
        1) HTTP的生命周期通過Request來界定,也就是一個Request 一個Response,那么HTTP1.0,這次HTTP請求就結束了。
        在HTTP1.1中進行了改進,使得有一個keep-alive,也就是說,在一個HTTP連接中,可以發(fā)送多個Request,接收多個Response。
        但是請記住 Request = Response , 在HTTP中永遠是這樣,也就是說一個request只能有一個response。而且這個response也是被動的,不能主動發(fā)起。

        教練,你BB了這么多,跟Websocket有什么關系呢? 
        _(:з」∠)_好吧,我正準備說Websocket呢。。 
        首先Websocket是基于HTTP協(xié)議的,或者說 借用了HTTP的協(xié)議來完成一部分握手。 
        在握手階段是一樣的 
        -------以下涉及專業(yè)技術內(nèi)容,不想看的可以跳過lol:,或者只看加黑內(nèi)容-------- 
        首先我們來看個典型的Websocket握手(借用Wikipedia的。。)

        熟悉HTTP的童鞋可能發(fā)現(xiàn)了,這段類似HTTP協(xié)議的握手請求中,多了幾個東西。
        我會順便講解下作用。

        Upgrade: websocket

        Connection: Upgrade


        這個就是Websocket的核心了,告訴Apache、Nginx等服務器: 注意啦,窩發(fā)起的是Websocket協(xié)議,快點幫我找到對應的助理處理~不是那個老土的HTTP。 

        Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

        Sec-WebSocket-Protocol: chat, superchat

        Sec-WebSocket-Version: 13


        首先,Sec-WebSocket-Key 是一個Base64 encode的值,這個是瀏覽器隨機生成的,告訴服務器:泥煤,不要忽悠窩,我要驗證尼是不是真的是Websocket助理。
        然后,Sec_WebSocket-Protocol 是一個用戶定義的字符串,用來區(qū)分同URL下,不同的服務所需要的協(xié)議。簡單理解:今晚我要服務A,別搞錯啦~
        最后,Sec-WebSocket-Version 是告訴服務器所使用的Websocket Draft(協(xié)議版本),在最初的時候,Websocket協(xié)議還在 Draft 階段,各種奇奇怪怪的協(xié)議都有,而且還有很多期奇奇怪怪不同的東西,什么Firefox和Chrome用的不是一個版本之類的,當初Websocket協(xié)議太多可是一個大難題。。不過現(xiàn)在還好,已經(jīng)定下來啦大家都使用的一個東西 脫水:服務員,我要的是13歲的噢→_→

        然后服務器會返回下列東西,表示已經(jīng)接受到請求, 成功建立Websocket啦! 

        HTTP/1.1 101 Switching Protocols

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

        Sec-WebSocket-Protocol: chat


        這里開始就是HTTP最后負責的區(qū)域了,告訴客戶,我已經(jīng)成功切換協(xié)議啦~ 

        Upgrade: websocket

        Connection: Upgrade


        依然是固定的,告訴客戶端即將升級的是Websocket協(xié)議,而不是mozillasocket,lurnarsocket或者shitsocket。
        然后,Sec-WebSocket-Accept 這個則是經(jīng)過服務器確認,并且加密過后的 Sec-WebSocket-Key。服務器:好啦好啦,知道啦,給你看我的ID CARD來證明行了吧。。
        后面的,Sec-WebSocket-Protocol 則是表示最終使用的協(xié)議。

        至此,HTTP已經(jīng)完成它所有工作了,接下來就是完全按照Websocket協(xié)議進行了。
        具體的協(xié)議就不在這闡述了。
        ------------------技術解析部分完畢------------------


         

        你TMD又BBB了這么久,那到底Websocket有什么鬼用,http long poll,或者ajax輪詢不都可以實現(xiàn)實時信息傳遞么。 


        三、Websocket的作用
        在講Websocket之前,我就順帶著講下 long poll 和 ajax輪詢 的原理。
        首先是 ajax輪詢 ,ajax輪詢 的原理非常簡單,讓瀏覽器隔個幾秒就發(fā)送一次請求,詢問服務器是否有新信息。
        場景再現(xiàn):
        客戶端:啦啦啦,有沒有新信息(Request)
        服務端:沒有(Response)
        客戶端:啦啦啦,有沒有新信息(Request)
        服務端:沒有。。(Response)
        客戶端:啦啦啦,有沒有新信息(Request)
        服務端:你好煩啊,沒有啊。。(Response)
        客戶端:啦啦啦,有沒有新消息(Request)
        服務端:好啦好啦,有啦給你。(Response)
        客戶端:啦啦啦,有沒有新消息(Request)
        服務端:。。。。。沒。。。。沒。。。沒有(Response) ---- loop


        long poll 
        long poll 其實原理跟 ajax輪詢 差不多,都是采用輪詢的方式,不過采取的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說,客戶端發(fā)起連接后,如果沒消息,就一直不返回Response給客戶端。直到有消息才返回,返回完之后,客戶端再次建立連接,周而復始。
        場景再現(xiàn)
        客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request)
        服務端:額。。等待到有消息的時候。。來 給你(Response)
        客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request) -loop

        從上面可以看出其實這兩種方式,都是在不斷地建立HTTP連接,然后等待服務端處理,可以體現(xiàn)HTTP協(xié)議的另外一個特點,被動性
        何為被動性呢,其實就是,服務端不能主動聯(lián)系客戶端,只能有客戶端發(fā)起。
        簡單地說就是,服務器是一個很懶的冰箱(這是個梗)(不會、不能主動發(fā)起連接),但是上司有命令,如果有客戶來,不管多么累都要好好接待。

        說完這個,我們再來說一說上面的缺陷(原諒我廢話這么多吧OAQ)
        從上面很容易看出來,不管怎么樣,上面這兩種都是非常消耗資源的。
        ajax輪詢 需要服務器有很快的處理速度和資源。(速度)
        long poll 需要有很高的并發(fā),也就是說同時接待客戶的能力。(場地大?。?br style="outline: 0px;">所以ajax輪詢 和long poll 都有可能發(fā)生這種情況。

        客戶端:啦啦啦啦,有新信息么?
        服務端:月線正忙,請稍后再試(503 Server Unavailable)
        客戶端:。。。。好吧,啦啦啦,有新信息么?
        服務端:月線正忙,請稍后再試(503 Server Unavailable)

        客戶端:

         


        然后服務端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我錯了。。這又是梗。。)


        --------------------------
        言歸正傳,我們來說Websocket吧
        通過上面這個例子,我們可以看出,這兩種方式都不是最好的方式,需要很多資源。
        一種需要更快的速度,一種需要更多的’電話’。這兩種都會導致’電話’的需求越來越高。
        哦對了,忘記說了HTTP還是一個無狀態(tài)協(xié)議。(感謝評論區(qū)的各位指出OAQ)
        通俗的說就是,服務器因為每天要接待太多客戶了,是個健忘鬼,你一掛電話,他就把你的東西全忘光了,把你的東西全丟掉了。你第二次還得再告訴服務器一遍。

        所以在這種情況下出現(xiàn)了,Websocket出現(xiàn)了。
        他解決了HTTP的這幾個難題。
        首先,被動性,當服務器完成協(xié)議升級后(HTTP->Websocket),服務端就可以主動推送信息給客戶端啦。
        所以上面的情景可以做如下修改。
        客戶端:啦啦啦,我要建立Websocket協(xié)議,需要的服務:chat,Websocket協(xié)議版本:17(HTTP Request)
        服務端:ok,確認,已升級為Websocket協(xié)議(HTTP Protocols Switched)
        客戶端:麻煩你有信息的時候推送給我噢。。
        服務端:ok,有的時候會告訴你的。
        服務端:balabalabalabala
        服務端:balabalabalabala
        服務端:哈哈哈哈哈啊哈哈哈哈
        服務端:笑死我了哈哈哈哈哈哈哈

        就變成了這樣,只需要經(jīng)過一次HTTP請求,就可以做到源源不斷的信息傳送了。(在程序設計中,這種設計叫做回調(diào),即:你有信息了再來通知我,而不是我傻乎乎的每次跑來問你)
        這樣的協(xié)議解決了上面同步有延遲,而且還非常消耗資源的這種情況。
        那么為什么他會解決服務器上消耗資源的問題呢?
        其實我們所用的程序是要經(jīng)過兩層代理的,即HTTP協(xié)議在Nginx等服務器的解析下,然后再傳送給相應的Handler(PHP等)來處理。
        簡單地說,我們有一個非??焖俚慕?span style="outline: 0px;font-weight: bolder;">線員(Nginx)
        ,他負責把問題轉交給相應的客服(Handler)
        本身接線員基本上速度是足夠的,但是每次都卡在客服(Handler)了,老有客服處理速度太慢。,導致客服不夠。
        Websocket就解決了這樣一個難題,建立后,可以直接跟接線員建立持久連接,有信息的時候客服想辦法通知接線員,然后接線員在統(tǒng)一轉交給客戶。
        這樣就可以解決客服處理速度過慢的問題了。

        同時,在傳統(tǒng)的方式上,要不斷的建立,關閉HTTP協(xié)議,由于HTTP是非狀態(tài)性的,每次都要 重新傳輸identity info(鑒別信息),來告訴服務端你是誰。 
        雖然接線員很快速,但是每次都要聽這么一堆,效率也會有所下降的,同時還得不斷把這些信息轉交給客服,不但浪費客服的 處理時間,而且還會在網(wǎng)路傳輸中消耗 過多的流量/時間。 
        但是Websocket只需要 一次HTTP握手,所以說整個通訊過程是建立在一次連接/狀態(tài)中,也就避免了HTTP的非狀態(tài)性,服務端會一直知道你的信息,直到你關閉請求,這樣就解決了接線員要反復解析HTTP協(xié)議,還要查看identity info的信息。 
        同時由 客戶主動詢問,轉換為 服務器(推送)有信息的時候就發(fā)送(當然客戶端還是等主動發(fā)送信息過來的。。),沒有信息的時候就交給接線員(Nginx),不需要占用本身速度就慢的 客服(Handler)了 
        -------------------- 
        至于怎么在不支持Websocket的客戶端上使用Websocket。。答案是: 不能 
        但是可以通過上面說的 long poll 和 ajax 輪詢來 模擬出類似的效果 
        ----- 
        _(:з」∠)_兩天寫了兩篇科普類文章。。好累OAQ,求贊。。 
        對啦,如果有錯誤,歡迎大家在底下留言指出噢~


        以下是騰訊云技術社區(qū)整理的 WebSocket原理說明 ——


        眾所周知,Web應用的通信過程通常是客戶端通過瀏覽器發(fā)出一個請求,服務器端接收請求后進行處理并返回結果給客戶端,客戶端瀏覽器將信息呈現(xiàn)。這種機制對于信息變化不是特別頻繁的應用可以良好支撐,但對于實時要求高、海量并發(fā)的應用來說顯得捉襟見肘,尤其在當前業(yè)界移動互聯(lián)網(wǎng)蓬勃發(fā)展的趨勢下,高并發(fā)與用戶實時響應是Web應用經(jīng)常面臨的問題,比如金融證券的實時信息、Web導航應用中的地理位置獲取、社交網(wǎng)絡的實時消息推送等。

        傳統(tǒng)的請求-響應模式的Web開發(fā)在處理此類業(yè)務場景時,通常采用實時通訊方案。比如常見的輪詢方案,其原理簡單易懂,就是客戶端以一定的時間間隔頻繁請求的方式向服務器發(fā)送請求,來保持客戶端和服務器端的數(shù)據(jù)同步。其問題也很明顯:當客戶端以固定頻率向服務器端發(fā)送請求時,服務器端的數(shù)據(jù)可能并沒有更新,帶來很多無謂請求,浪費帶寬,效率低下。

        基于Flash,AdobeFlash通過自己的Socket實現(xiàn)完成數(shù)據(jù)交換,再利用Flash暴露出相應的接口給JavaScript調(diào)用,從而達到實時傳輸目的。此方式比輪詢要高效,且因為Flash安裝率高,應用場景廣泛。然而,移動互聯(lián)網(wǎng)終端上Flash的支持并不好:IOS系統(tǒng)中無法支持Flash,Android雖然支持Flash但實際的使用效果差強人意,且對移動設備的硬件配置要求較高。2012年Adobe官方宣布不再支持Android4.1+系統(tǒng),宣告了Flash在移動終端上的死亡。

        傳統(tǒng)的Web模式在處理高并發(fā)及實時性需求的時候,會遇到難以逾越的瓶頸,需要一種高效節(jié)能的雙向通信機制來保證數(shù)據(jù)的實時傳輸。在此背景下,基于HTML5規(guī)范的、有Web TCP之稱的 WebSocket應運而生。早期HTML5并沒有形成業(yè)界統(tǒng)一的規(guī)范,各個瀏覽器和應用服務器廠商有著各異的類似實現(xiàn),如IBM的MQTT、Comet開源框架等。直到2014年,HTML5終于塵埃落地,正式落實為實際標準規(guī)范,各個應用服務器及瀏覽器廠商逐步開始統(tǒng)一,在 JavaEE7中也實現(xiàn)了WebSocket協(xié)議。至此無論是客戶端還是服務端的WebSocket都已完備。用戶可以查閱HTML5規(guī)范,熟悉新的HTML協(xié)議規(guī)范及WebSocket支持。

        WebSocket 機制

        以下簡要介紹一下WebSocket的原理及運行機制。

        WebSocket是HTML5下一種新的協(xié)議。它實現(xiàn)了瀏覽器與服務器全雙工通信,能更好的節(jié)省服務器資源和帶寬并達到實時通訊的目的。它與HTTP一樣通過已建立的TCP連接來傳輸數(shù)據(jù),但是它和HTTP最大不同是:

        • WebSocket是一種雙向通信協(xié)議。在建立連接后,WebSocket服務器端和客戶端都能主動向對方發(fā)送或接收數(shù)據(jù),就像Socket一樣;

        • WebSocket需要像TCP一樣,先建立連接,連接成功后才能相互通信。

        傳統(tǒng)HTTP客戶端與服務器請求響應模式如下圖所示:

        WebSocket模式客戶端與服務器請求響應模式如下圖:

        上圖對比可以看出,相對于傳統(tǒng)HTTP每次請求-應答都需要客戶端與服務端建立連接的模式,WebSocket是類似Socket的TCP長連接通訊模式。一旦WebSocket連接建立后,后續(xù)數(shù)據(jù)都以幀序列的形式傳輸。在客戶端斷開WebSocket連接或Server端中斷連接前,不需要客戶端和服務端重新發(fā)起連接請求。在海量并發(fā)及客戶端與服務器交互負載流量大的情況下,極大的節(jié)省了網(wǎng)絡帶寬資源的消耗,有明顯的性能優(yōu)勢,且客戶端發(fā)送和接受消息是在同一個持久連接上發(fā)起,實時性優(yōu)勢明顯。

        相比HTTP長連接,WebSocket有以下特點:

        • 是真正的全雙工方式,建立連接后客戶端與服務器端是完全平等的,可以互相主動請求。而HTTP長連接基于HTTP,是傳統(tǒng)的客戶端對服務器發(fā)起請求的模式。

        • HTTP長連接中,每次數(shù)據(jù)交換除了真正的數(shù)據(jù)部分外,服務器和客戶端還要大量交換HTTP header,信息交換效率很低。Websocket協(xié)議通過第一個request建立了TCP連接之后,之后交換的數(shù)據(jù)都不需要發(fā)送 HTTP header就能交換數(shù)據(jù),這顯然和原有的HTTP協(xié)議有區(qū)別所以它需要對服務器和客戶端都進行升級才能實現(xiàn)(主流瀏覽器都已支持HTML5)。此外還有 multiplexing、不同的URL可以復用同一個WebSocket連接等功能。這些都是HTTP長連接不能做到的。

        下面再通過客戶端和服務端交互的報文對比WebSocket通訊與傳統(tǒng)HTTP的不同點:

        在客戶端,new WebSocket實例化一個新的WebSocket客戶端對象,請求類似 ws://yourdomain:port/path 的服務端WebSocket URL,客戶端WebSocket對象會自動解析并識別為WebSocket請求,并連接服務端端口,執(zhí)行雙方握手過程,客戶端發(fā)送數(shù)據(jù)格式類似:

        GET /webfin/websocket/ HTTP/1.1

        Host: localhost

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==

        Origin: http://localhost:8080

        Sec-WebSocket-Version: 13


        可以看到,客戶端發(fā)起的WebSocket連接報文類似傳統(tǒng)HTTP報文,Upgrade:websocket參數(shù)值表明這是WebSocket類型請求,Sec-WebSocket-Key是WebSocket客戶端發(fā)送的一個 base64編碼的密文,要求服務端必須返回一個對應加密的Sec-WebSocket-Accept應答,否則客戶端會拋出Error during WebSocket handshake錯誤,并關閉連接。

        服務端收到報文后返回的數(shù)據(jù)格式類似:

        HTTP/1.1 101 Switching Protocols

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=


        Sec-WebSocket-Accept的值是服務端采用與客戶端一致的密鑰計算出來后返回客戶端的,HTTP/1.1 101 Switching Protocols表示服務端接受WebSocket協(xié)議的客戶端連接,經(jīng)過這樣的請求-響應處理后,兩端的WebSocket連接握手成功, 后續(xù)就可以進行TCP通訊了。用戶可以查閱WebSocket協(xié)議棧了解WebSocket客戶端和服務端更詳細的交互數(shù)據(jù)格式。

        在開發(fā)方面,WebSocket API 也十分簡單:只需要實例化 WebSocket,創(chuàng)建連接,然后服務端和客戶端就可以相互發(fā)送和響應消息。在WebSocket 實現(xiàn)及案例分析部分可以看到詳細的 WebSocket API 及代碼實現(xiàn)。

        騰訊云公網(wǎng)有日租類型七層負載均衡轉發(fā)部分支持Websocket,目前包括英魂之刃、銀漢游戲等多家企業(yè)已接入使用。當出現(xiàn)不兼容問題時,請修改websocket配置,websocket server不校驗下圖中圈出的字段:



        一個使用WebSocket應用于視頻的業(yè)務思路如下:

        • 使用心跳維護websocket鏈路,探測客戶端端的網(wǎng)紅/主播是否在線

        • 設置負載均衡7層的proxy_read_timeout默認為60s

        • 設置心跳為50s,即可長期保持Websocket不斷開





        鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布

        ??????

        ??長按上方微信二維碼 2 秒





        感謝點贊支持下哈 

        瀏覽 47
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            无码一区一区 | 日逼逼视频 | 女人张开腿让男桶喷水高潮 | 日韩精品一区二区三区免费观看 | 国产内射视频免费观看 | 中文字幕日产av 日本欧美久久久久免费播放网 | 肏屄乱伦视频 | 中文在线视频 | 欧美一级影视 | japanese奶水流浆久久爱 |