客戶端向服務器請求數據,服務器立即將數據返回給客戶端。 如果客戶端沒有得到想要的數據(比如返回的結果告訴客戶端正在處理數據),客戶端繼續發送請求,服務器繼續立即響應,周而復始。
這種實時獲取數據的方式比較粗糙,優點是編程簡單,客戶端發送請求,服務端實時響應。 主要有兩個缺點:
那么短輪詢適合哪些使用場景呢? 按照我的理解,如果數據變化頻繁或者可以預計數據在短時間內變化一次,可以使用短輪詢,比如:
用戶在 PC 上購買東西以激活網頁。 由于 PC 和 web 沒有連接,我們希望用戶盡快完成支付。 在這種情況下,短輪詢是一種可用的方法,開發簡單,服務端直接提供接口告訴客戶端訂單狀態。 客戶端只需要每5秒請求一次,得到結果就不需要再請求了。
使用短輪詢時,要注意請求數上限的控制。 例如服務器接收http數據,用戶請求100次后仍未檢測到付款,則可以彈出“付款完成后請到我的訂單頁面查看”的窗口,無需請求。
長輪詢
長輪詢是另一種實時獲取數據的方式。 看一下過程:
本質沒變。 客戶端仍然在向服務器發送請求,而沒有收到它想要的數據。 不同的是,服務器不再直接響應請求,而是暫停請求,自行調度。 判斷數據的變化,如果有變化,則立即返回給客戶端,如果沒有變化,則等待超時。
可以明顯看出,長輪詢的好處是客戶端請求少很多,避免了不必要的客戶端請求。 缺點是服務器會掛掉大量請求增加資源消耗,并且服務器對HTTP請求的并發數有限制。 的。
微信網頁版的登錄就是長輪詢的典型例子:
從圖中可以看出,客戶端不停地向服務器發送請求,但是服務器并沒有在第一時間給出響應,所以客戶端等待超時繼續發送請求。
總的來說服務器接收http數據,我理解長輪詢一般用的比較多,而短輪詢對于簡單的編程更重要,適合小型應用。 像微信網頁登錄,幾千個用戶同時登錄,一段時間后服務器收到幾千個請求處理。 堆積機器來分攤每個服務器上的處理請求數并不是解決問題的辦法。
上面介紹了兩種輪詢方式,但是兩者結合起來有明顯的缺點。 總結起來有以下幾點:
因此,我們能做的最好的事情就是:客戶端和服務器之間有一條路徑。 當服務器上的數據發生變化時,服務器可以主動推送給客戶端。 它是在HTML5之后誕生的協議來實現這一點。 雖然這是一個新的協議,但它也是基于 HTTP 協議的。
看一下原理,很簡單:
客戶端首先通過HTTP協議向服務端發送幾個特殊的header,告訴服務端我現在發起一個HTTP請求,但是我要升級到:
只要服務端支持該協議(Tomcat7和Jetty7之后支持),服務端在收到請求并建立連接成功后,會返回Sec--Accept和Sec--這兩個header給客戶端,Http Status為101 . 協議切換成功,這樣客戶端和服務端只要任何一方不斷開連接就可以基于這條路徑進行通信。
再說說相對于上面提到的長短輪詢在帶寬資源上的節省。 有一個測試,假設HTTP Header是871字節。 由于數據傳輸是基于幀的,因此幀傳輸效率更高。 與長短輪詢相比,2個字節就可以代替871字節的Header。 測試結果是:
對于每秒相同數量的客戶端輪詢,當頻率高達10W/s時,輪詢需要消耗665Mbps,而只有1.526Mbps,接近435倍。
它實現了real-time實時,節省了大量的帶寬資源,但是我理解它也有自己的問題,就是開發成本比較高。 這里的開發成本并不是指自己實現。 這可以直接使用 Netty 來完成——在 Java 語言層面,API 非常簡單,它提供了完整的實現,而真正的開發成本在于分布式環境中的數據同步問題。
比如有一個在線聊天系統,有10萬人同時在線。 這時,用戶發送一條1K的語音消息。 單機維持10W連接是可以的(這不是HTTP請求,所以不受連接池數量的影響),問題出在帶寬上。 單機同時向10W用戶推送1K語音消息,至少需要10M帶寬。 這只是單純的把數據往外推,沒有考慮數據進來的場景,實際操作過程需要更多的帶寬。 對于企業來說,這是一個很大的問題。 一個非常大的成本。
所以在連接數較多的場景下會使用集群(實際上即使連接數不多,也會為了高可用而使用集群)。 10W并發分布5臺機器,每臺機器平均有2W個連接。 考慮集群下會出現的問題:
Client 1將數據發送給Server 1,所有連接到Server 1的client都可以推送語音,但是問題是:
其他需要考慮的問題太多就不一一列舉了。 總而言之,在請求量大、并發高的場景下使用,代碼開發成本是非常高的。 但是由于它可以實現服務器到客戶端的實時數據推送,節省了大量的帶寬資源,所以IM、音視頻、彈幕等很多應用都會用到它。
總結
以上就是本文的全部內容。 希望本文的內容對您的學習或工作有一定的參考學習價值。 有什么問題可以留言交流。 感謝您對場景 3 的支持。