天天看點

http3 替代websocket_http協定與websocket協定(轉)

一、WebSocket是HTML5中的協定,支援持久連接配接;而Http協定不支援持久連接配接。

首先HTMl5指的是一系列新的API,或者說新規範,新技術。WebSocket是HTML5中新協定、新API.

Http協定本身隻有1.0和1.1,也就是所謂的Keep-alive,把多個Http請求合并為一個。

二、WebSocket是什麼樣的協定,具體有什麼優點。

首先,相對于Http這種非持久的協定來說,WebSocket是一種持久化的協定。

舉例說明:

(1)Http的生命周期通過Request來界定,也就是Request一個Response,那麼在Http1.0協定中,這次Http請求就結束了。

在Http1.1中進行了改進,是的有一個Keep-alive,也就是說,在一個Http連接配接中,可以發送多個Request,接收多個Response。

但是必須記住,在Http中一個Request隻能對應有一個Response,而且這個Response是被動的,不能主動發起。

(2)WebSocket是基于Http協定的,或者說借用了Http協定來完成一部分握手,在握手階段與Http是相同的。

首先我們來看個典型的Websocket握手(借用Wikipedia的。。)

GET /chat HTTP/1.1

Host: server.example.com

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

Origin: http://example.com

熟悉HTTP的童鞋可能發現了,這段類似HTTP協定的握手請求中,多了幾個東西。

我會順便講解下作用。

Upgrade: websocket

Connection: Upgrade

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

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

首先,Sec-WebSocket-Key 是一個Base64 encode的值,這個是浏覽器随機生成的,告訴伺服器:泥煤,不要忽悠窩,我要驗證尼是不是真的是Websocket助理。

然後,Sec_WebSocket-Protocol 是一個使用者定義的字元串,用來區分同URL下,不同的服務所需要的協定。簡單了解:今晚我要服務A,别搞錯啦~

最後,Sec-WebSocket-Version 是告訴伺服器所使用的Websocket Draft(協定版本),在最初的時候,Websocket協定還在 Draft 階段,各種奇奇怪怪的協定都有,而且還有很多期奇奇怪怪不同的東西,什麼Firefox和Chrome用的不是一個版本之類的,當初Websocket協定太多可是一個大難題。。不過現在還好,已經定下來啦~大家都使用的一個東西~ 脫水:服務員,我要的是13歲的噢→_→

然後伺服器會傳回下列東西,表示已經接受到請求, 成功建立Websocket啦!

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Sec-WebSocket-Protocol: chat

這裡開始就是HTTP最後負責的區域了,告訴客戶,我已經成功切換協定啦~

Upgrade: websocket

Connection: Upgrade

依然是固定的,告訴用戶端即将更新的是Websocket協定,而不是mozillasocket,lurnarsocket或者shitsocket。

然後,Sec-WebSocket-Accept 這個則是經過伺服器确認,并且加密過後的 Sec-WebSocket-Key。伺服器:好啦好啦,知道啦,給你看我的ID CARD來證明行了吧。。

後面的,Sec-WebSocket-Protocol 則是表示最終使用的協定。

至此,HTTP已經完成它所有工作了,接下來就是完全按照Websocket協定進行了。

其後是WebSocket協定的工作。

三、Long poll 和Ajax輪詢以及WebSocket的原理

1、Ajax輪詢的原理。

場景如下:

用戶端:啦啦啦,有沒有新資訊(Request)

服務端:沒有(Response)

用戶端:啦啦啦,有沒有新資訊(Request)

服務端:沒有。。(Response)

用戶端:啦啦啦,有沒有新資訊(Request)

服務端:你好煩啊,沒有啊。。(Response)

用戶端:啦啦啦,有沒有新消息(Request)

服務端:好啦好啦,有啦給你。(Response)

用戶端:啦啦啦,有沒有新消息(Request)

服務端:。。。。。沒。。。。沒。。。沒有(Response) ---- loop

2、long poll的原理。

long poll 其實原理跟 ajax輪詢 差不多,都是采用輪詢的方式,不過采取的是阻塞模型(一直打電話,沒收到就不挂電話),也就是說,用戶端發起連接配接後,如果沒消息,就一直不傳回Response給用戶端。直到有消息才傳回,傳回完之後,用戶端再次建立連接配接,周而複始。

場景如下:

用戶端:啦啦啦,有沒有新資訊,沒有的話就等有了才傳回給我吧(Request)

服務端:額。。 (等待到有消息的時候)。。來 給你(Response)

用戶端:啦啦啦,有沒有新資訊,沒有的話就等有了才傳回給我吧(Request) -loop

從上面可以看出其實這兩種方式,都是在不斷地建立HTTP連接配接,然後等待服務端處理,可以展現HTTP協定的另外一個特點,被動性。

何為被動性呢,其實就是,服務端不能主動聯系用戶端,隻能有用戶端發起。

簡單地說就是,伺服器是一個很懶的冰箱(這是個梗)(不會、不能主動發起連接配接),但是上司有指令,如果有客戶來,不管多麼累都要好好接待。

說完這個,我們再來說一說上面的缺陷

從上面很容易看出來,不管怎麼樣,上面這兩種都是非常消耗資源的。

ajax輪詢 需要伺服器有很快的處理速度和資源。(速度)

long poll 需要有很高的并發,也就是說同時接待客戶的能力。(場地大小)

是以ajax輪詢 和long poll 都有可能發生這種情況。

用戶端:啦啦啦啦,有新資訊麼?

服務端:月線正忙,請稍後再試(503 Server Unavailable)

用戶端:。。。。好吧,啦啦啦,有新資訊麼?

服務端:月線正忙,請稍後再試(503 Server Unavailable)

用戶端:

http3 替代websocket_http協定與websocket協定(轉)

然後服務端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。

3、WebSocket的原理。

通過上面這個例子,我們可以看出,這兩種方式都不是最好的方式,需要很多資源。

一種需要更快的速度,一種需要更多的'電話'。這兩種都會導緻'電話'的需求越來越高。

哦對了,忘記說了HTTP還是一個狀态協定。

通俗的說就是,伺服器因為每天要接待太多客戶了,是個健忘鬼,你一挂電話,他就把你的東西全忘光了,把你的東西全丢掉了。你第二次還得再告訴伺服器一遍。

是以在這種情況下出現了,Websocket出現了。

他解決了HTTP的這幾個難題。

首先,被動性,當伺服器完成協定更新後(HTTP->Websocket),服務端就可以主動推送資訊給用戶端啦。

是以上面的情景可以做如下修改。

用戶端:啦啦啦,我要建立Websocket協定,需要的服務:chat,Websocket協定版本:17(HTTP Request)

服務端:ok,确認,已更新為Websocket協定(HTTP Protocols Switched)

用戶端:麻煩你有資訊的時候推送給我噢。。

服務端:ok,有的時候會告訴你的。

服務端:balabalabalabala

服務端:balabalabalabala

服務端:哈哈哈哈哈啊哈哈哈哈

服務端:笑死我了哈哈哈哈哈哈哈

就變成了這樣,隻需要經過一次HTTP請求,就可以做到源源不斷的資訊傳送了。(在程式設計中,這種設計叫做回調,即:你有資訊了再來通知我,而不是我傻乎乎的每次跑來問你)

這樣的協定解決了上面同步有延遲,而且還非常消耗資源的這種情況。

那麼為什麼他會解決伺服器上消耗資源的問題呢?

其實我們所用的程式是要經過兩層代理的,即HTTP協定在Nginx等伺服器的解析下,然後再傳送給相應的Handler(PHP等)來處理。

簡單地說,我們有一個非常快速的接線員(Nginx),他負責把問題轉交給相應的客服(Handler)。

本身接線員基本上速度是足夠的,但是每次都卡在客服(Handler)了,老有客服處理速度太慢。,導緻客服不夠。

Websocket就解決了這樣一個難題,建立後,可以直接跟接線員建立持久連接配接,有資訊的時候客服想辦法通知接線員,然後接線員在統一轉交給客戶。

這樣就可以解決客服處理速度過慢的問題了。

同時,在傳統的方式上,要不斷的建立,關閉HTTP協定,由于HTTP是非狀态性的,每次都要重新傳輸identity info(鑒别資訊),來告訴服務端你是誰。

雖然接線員很快速,但是每次都要聽這麼一堆,效率也會有所下降的,同時還得不斷把這些資訊轉交給客服,不但浪費客服的處理時間,而且還會在網路傳輸中消耗過多的流量/時間。

但是Websocket隻需要一次HTTP握手,是以說整個通訊過程是建立在一次連接配接/狀态中,也就避免了HTTP的非狀态性,服務端會一直知道你的資訊,直到你關閉請求,這樣就解決了接線員要反複解析HTTP協定,還要檢視identity info的資訊。

同時由客戶主動詢問,轉換為伺服器(推送)有資訊的時候就發送(當然用戶端還是等主動發送資訊過來的。。),沒有資訊的時候就交給接線員(Nginx),不需要占用本身速度就慢的客服(Handler)了

--------------------

至于怎麼在不支援Websocket的用戶端上使用Websocket。。答案是:不能

但是可以通過上面說的 long poll 和 ajax 輪詢來 模拟出類似的效果