python realtime

理論知識

嘗試解決服務(wù)器推送的問題, web都是拉取數(shù)據(jù):瀏覽器發(fā)出請求到服務(wù)器,服務(wù)器會產(chǎn)生并且發(fā)送回響應(yīng) 但是,如果有需要將數(shù)據(jù)主動從服務(wù)器推送到瀏覽器該怎么辦呢?

長輪詢long-polling

解決的方法:瀏覽器發(fā)出ajax請求到服務(wù)器,要求更新,但是這個常用的瀏覽器和服務(wù)器之間的推送方法,有一個問題: 如果服務(wù)器沒有什么要發(fā)送,它會保持連接打開,直到為用戶提供一些數(shù)據(jù),客戶端收到響應(yīng)后,會發(fā)出另外的一個請求,獲得更多的數(shù)據(jù) 上面的這種技術(shù)被稱為long-polling,長輪詢
顯然,這種方法不太高效,大多數(shù)情況下,信噪比是非常高的(無用的數(shù)據(jù)比有用的數(shù)據(jù)),因?yàn)檫@樣更多的時(shí)間將花在處理http請求(比如解析和驗(yàn)證報(bào)頭),而不是實(shí)際數(shù)據(jù)發(fā)送到客戶端 不幸的是,這種長輪詢的方法是目前將數(shù)據(jù)推送到客戶端最適合的方式
基于HTTP/1.1情況好轉(zhuǎn)了一點(diǎn),TCP連接可以使用 Keep-Alive頭,默認(rèn)情況下, 連接在請求發(fā)起后將保持打開狀態(tài)。 此功能使長輪詢延遲得到了降低,這樣就沒有必要為每個輪詢請求重新打開TCP連接 HTTP/1.1還引入了 塊傳輸協(xié)議 。 它允許講響應(yīng)分解為成更小的數(shù)據(jù)塊, 并將它們立即發(fā)送到客戶端,而不是一直等到完成HTTP請求 不幸的是,有些不兼容這個功能的代理服務(wù)器還是試圖在轉(zhuǎn)發(fā)之前緩存整個響應(yīng),所以客戶端將不會收到任何數(shù)據(jù),直到代理認(rèn)為http請求已經(jīng)完成 雖然看起來,web還是能正常工作-因?yàn)榭蛻舳俗罱K還是會得到來自服務(wù)器的響應(yīng),但是它打破了為實(shí)時(shí)而設(shè)計(jì)的塊傳輸協(xié)議的整體思路

其他方法

2006年9月,opera為它的瀏覽器實(shí)現(xiàn)了試驗(yàn)性的服務(wù)事件發(fā)送功能,雖然sse和塊傳輸協(xié)議很相似,但是還是不同的協(xié)議,而且有更好的客戶端api 2009年4月23日,SSE得到WHATWG批準(zhǔn),得到幾乎所有的現(xiàn)代的桌面瀏覽器(Internet Explorer的除外)的支持 還有其他的技術(shù),比如 forever-iframe, 這是兩種可以為Internet Explorer版本低于8做跨域推送的技術(shù)之一(另一個是 jsonp, 以及 HTMLFILE 等 總之,所有這些基于HTTP的折中方案都可以叫做 Comet

方法利弊

long-polling,長輪詢是昂貴的,但是兼容性很好 塊傳輸協(xié)議效率更高,但有可能不是所有的客戶端都能正常工作,并且如果沒有某種形式的探測都無法發(fā)現(xiàn)問題的存在 sse也不錯,但不是所有的瀏覽器都支持,比較好的是有辦法在建立連接前,就知道它是否支持
這些方法都有一個問題,它們都只提供一種方式將數(shù)據(jù)從服務(wù)器推送到客戶端,而不是建立雙向通信,客戶端每次想發(fā)送一些數(shù)據(jù)的時(shí)候,將不得不使用ajax請求到服務(wù)器,這樣會增加延遲,并且服務(wù)器也會產(chǎn)生額外的負(fù)載

邂逅websockets

雖然websockets不是什么新技術(shù),但是經(jīng)歷了幾個不兼容的迭代后該規(guī)范終于通過了,rfc編號rfc-6455 簡而言之,基于websocket的服務(wù)器和客戶端之間建立的是基于tcp的雙向連接,連接的建立使用兼容http的握手協(xié)議,加上額外的websocket相關(guān)的頭,并具有額外的協(xié)議層次劃分,所以它不僅僅是一個從瀏覽器中打開原始的tcp連接
websocket協(xié)議的最大問題是:瀏覽器的支持,防火墻,代理服務(wù)器和防病毒應(yīng)用的支持,企業(yè)防火墻和代理服務(wù)器通常因各種原因阻止的WebSocket連接。 有些代理服務(wù)器不能處理WebSocket在端口80上連接 - 他們認(rèn)為這是一般的HTTP請求,并嘗試緩存它。 有HTTP掃描組件的殺毒軟件也不允許WebSocket連接 無論如何,websocket來建立的客戶端和服務(wù)器之間的雙向通信是最好的方式,但是不能單一的用來解決推送問題

用例

如果您的應(yīng)用程序大多是從服務(wù)器推送數(shù)據(jù),基于HTTP的傳輸會工作得很好。 但是,如果瀏覽器支持WebSocket的傳輸并且WebSocket的連接是可以建立的,它將是更好的選擇 總而言之, 最好的辦法是:嘗試打開的WebSocket連接, 如果失敗 - 嘗試回退到基于HTTP傳輸。 當(dāng)然也有可以”升級”連接 - 首先使用長輪詢(long-polling), 然后嘗試建立WebSocket的連接。 如果成功,就切換到WebSocket的連接。 雖然這種做法可能會降低初始連接的時(shí)間, 需要注意服務(wù)器端實(shí)現(xiàn), 以避免但在兩者連接之間切換時(shí)發(fā)生任何的跳變情況(race conditions)

polyfill庫

為所有已知的瀏覽器提供變通方案,搞定代理和防火墻的問題,尤其是從頭開始處理這些問題,是非常困難的,幸運(yùn)的是,已經(jīng)有人提出盡可能穩(wěn)定的解決方案 有一些 polyfill庫,像sockjs 庫 , socket.io 庫 , faye和其他一些框架,實(shí)現(xiàn)了基于各種不同的傳輸實(shí)現(xiàn)上的類WebSocket的 API 雖然他們所提供的服務(wù)器和客戶端API不盡相同,但他們有著共同的理念: 在給定的情況下用最好的傳輸方案,并且提供一致的服務(wù)器端API 例如,如果瀏覽器支持WebSocket協(xié)議,polyfill將嘗試建立WebSocket連接。 如果失敗了,他們將下降回到下一個最好的傳輸協(xié)議。 Engine.IO使用稍微不同的方法 - 他先建立長輪詢連接(long-polling),并嘗試在后臺升級到WebSocket 在任何情況下 - 這些庫將嘗試建立雙向連接到服務(wù)器上使用最可靠的傳輸。 不幸的是,在使用Socket.IO 0.8.x的時(shí)候有較差的體驗(yàn)。 我一般在我自己的項(xiàng)目中使用 sockjs-tornado, 即使我自己寫了 TornadIO2。 Socket.IO早期的server實(shí)現(xiàn)是基于 Tornado]的

服務(wù)器端

基于wsgi的服務(wù)器不能被用于創(chuàng)建實(shí)時(shí)應(yīng)用, 因?yàn)閣sgi協(xié)議是同步的,wsgi服務(wù)器一次只能處理一個請求

回顧長輪詢long-polling傳輸
客戶端打開http連接到服務(wù)器,獲得更多的數(shù)據(jù)

無可用的數(shù)據(jù),服務(wù)器保持連接打開并等待數(shù)據(jù)發(fā)送

因?yàn)榉?wù)器無法處理任何其他請求,一切都將被阻塞

偽代碼表示:
def handle_request(request):
    data = get_more_data(request)
    return send_response(data)

如果get_more_data阻塞了,那整個服務(wù)器就會被阻塞,不能處理請求了
當(dāng)然,可以每個請求創(chuàng)建線程,但這非常低效。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 初涉IM,首先我有這么幾個問題需要弄明白: Socket 和 WebSocket 有哪些區(qū)別和聯(lián)系? WebSoc...
    夜幕青雨閱讀 11,461評論 8 39
  • WebSocket簡介 談到Web實(shí)時(shí)推送,就不得不說WebSocket。在WebSocket出現(xiàn)之前,很多網(wǎng)站為...
    吧啦啦小湯圓閱讀 8,330評論 15 75
  • 那一天 你輕輕地一聲呼喚 撥動了我心中最柔軟的那根弦 從此夜夜 你成了我心底的一首歌 當(dāng)月光漫過月季飄香的窗前 當(dāng)...
    伊清歡閱讀 316評論 7 6
  • 媽,后半夜,你入我夢。 還是染青的大襟布衫,黑色的褲子。頭發(fā)不亂,慈慈地看著我。 “媽,你……”突然間看到你,我有...
    八里山人程遠(yuǎn)河閱讀 830評論 23 34

友情鏈接更多精彩內(nèi)容