日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
服務(wù)器推送事件:一種從服務(wù)器流式推送事件的簡易方法

哈嘍!昨天我見識到了一種我以前從沒見過的從服務(wù)器推送事件的炫酷方法:服務(wù)器推送事件server-sent events!如果你只需要讓服務(wù)器發(fā)送事件,相較于 Websockets,它們或許是一個更簡便的選擇。

應(yīng)城網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項目制作,到程序開發(fā),運(yùn)營維護(hù)。成都創(chuàng)新互聯(lián)于2013年成立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運(yùn)維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)

我會聊一聊它們的用途、運(yùn)作原理,以及我昨日在試著運(yùn)行它們的過程中遇到的幾個錯誤。

問題:從服務(wù)器流式推送更新

現(xiàn)在,我有一個啟動虛擬機(jī)的 Web 服務(wù),客戶端輪詢服務(wù)器,直到虛擬機(jī)啟動。但我并不想使用輪詢方式。

相反,我想讓服務(wù)器流式推送更新。我跟 Kamal 說我要用 Websockets 來實現(xiàn)它,而他建議使用服務(wù)器推送事件不失為一個更簡便的選擇!

我登時就愣住了——那什么玩意???聽起來像是些我從來沒見過的稀罕玩意兒。于是乎我就查了查。

服務(wù)器推送事件就是個 HTTP 請求協(xié)議

下文便是服務(wù)器推送事件的運(yùn)作流程。我-很-高-興-地了解到它們就是個 HTTP 請求協(xié)議。

1.客戶端提出一個 GET 請求(舉個例子)https://yoursite.com/events 2.客戶端設(shè)置 Connection: keep-alive,這樣我們就能有一個長連接 3.服務(wù)器設(shè)置設(shè)置一個 Content-Type: text/event-stream 響應(yīng)頭 4.服務(wù)器開始推送事件,就比如下文這樣:

event: status
data: one

舉個例子,這里是當(dāng)我借助 curl 發(fā)送請求時,一些服務(wù)器推送事件的樣子:

$ curl -N 'http://localhost:3000/sessions/15/stream'
event: panda
data: one
event: panda
data: two
event: panda
data: three
event: elephant
data: four

服務(wù)器可以根據(jù)時間推移緩慢推送事件,并且客戶端也能夠在它們到來時讀取它們。你也可以將 JSON 或任何你想要的東西放在事件當(dāng)中,就比如 data: {'name': 'ahmed'}。

線路協(xié)議真的很簡單(只需要設(shè)置 event: 和 data:,或者如果你愿意,可設(shè)置為 id: 和 retry:),所以你并不需要任何花里胡哨的服務(wù)器庫來實現(xiàn)服務(wù)器推送事件。

JavaScript 的代碼也超級簡單(僅使用 EventSource)

以下是用于流式服務(wù)器推送事件的瀏覽器 JavaScript 的代碼。(我從 服務(wù)器推送事件的 MND 頁面 得到的這個范例)

你可以訂閱所有事件,也可以為不同類型的事件使用不同的處理程序。這里我有一個只接受類型為 panda 的事件的處理程序(就像我們的服務(wù)器在上一節(jié)中推送的那樣)。

const evtSource = new EventSource("/sessions/15/stream", { withCredentials: true })
evtSource.addEventListener("panda", function(event) {
  console.log("status", event)
});

客戶端在中途不能推送更新

不同于 Websockets,服務(wù)器推送事件不允許大量的來回事件通訊。(這體現(xiàn)在它的字眼中 —— 服務(wù)器 推送所有事件)。初始的時候客戶端發(fā)出一個請求,然后服務(wù)器發(fā)出一連串響應(yīng)。

如果 HTTP 連接結(jié)束,它會自動重連

使用 EventSource 發(fā)出的 HTTP 請求和常規(guī) HTTP 請求有一個很大的區(qū)別,MDN 文檔中對此有所說明:

默認(rèn)情況下,如果客戶端和服務(wù)器之間的連接斷開,則連接會重啟。請使用 .close() 方法來終止連接。

很奇怪,一開始我真的被它嚇到了:我打開了一個連接,然后在服務(wù)器端將其關(guān)閉,然后兩秒過后客戶端向我的傳送終端發(fā)送了另一條請求!

我覺得這里可能是因為連接在完成之前意外斷開了,所以客戶端自動重新打開了它以防止類似情況再發(fā)生。

所以如果你不想讓客戶端繼續(xù)重試,你就得通過調(diào)用 .close() 直截了當(dāng)?shù)仃P(guān)閉連接。

這里還有些其它特性

你還能在服務(wù)器推送事件中設(shè)置 id: 和 retry: 字段。似乎,如果你在服務(wù)器推送事件上設(shè)置,那么當(dāng)重新連接時,客戶端將發(fā)送一個 Last-Event-ID 響應(yīng)頭,帶有它收到的最后一個 ID???

我發(fā)現(xiàn) W3C 的服務(wù)器推送事件頁面 令人驚訝地容易理解。

在設(shè)置服務(wù)器推送事件的時候我遇到了兩個錯誤

我在 Rails 中使用服務(wù)器推送事件時遇到了幾個問題,我認(rèn)為這些問題挺有趣的。其中一個緣于 Nginx,另一個是由 Rails 引起的。

問題一:我不能在事件推送的過程中暫停

這個奇怪的錯誤是在我做以下操作時出現(xiàn)的:

def handler
    # SSE is Rails' built in server-sent events thing
    sse = SSE.new(response.stream, event: "status")
    sse.write('event')
    sleep 1
    sse.write('another event')
end

它會寫入第一個事件,但不能寫入第二個事件。我對此-非-常-困-惑,然后放開腦洞,試著理解 Ruby 中的 sleep 是如何運(yùn)作的。但是 Cass 將我引領(lǐng)到一個與我有著相同困惑的 Stack Overflow 問答帖,而這里包含了讓我為之震驚的回答!

事實證明,問題出在我的 Rails 服務(wù)器位于 Nginx 之后,似乎 Nginx 默認(rèn)使用 HTTP/1.0 向上游服務(wù)器發(fā)起請求(為啥?都 2021 年了,還這么干?我相信這其中一定有合乎情理的解釋,也許是為了向下兼容之類的)。

所以客戶端(Nginx)會在服務(wù)器推送第一個事件之后直接關(guān)閉連接。我覺得如果在我推送第二個事件的過程中 沒有 暫停,它繼續(xù)正常工作,基本上就是服務(wù)器在連接關(guān)閉之前和客戶端在爭速度,爭著推送第二部分響應(yīng),如果我這邊推送速度足夠快,那么服務(wù)器就會贏得比賽。

我不確定為什么使用 HTTP/1.0 會使客戶端的連接關(guān)閉(可能是因為服務(wù)器在每個事件結(jié)尾寫入了兩個換行符?),但因為服務(wù)器推送事件是一個比較新的玩意兒,HTTP/1.0 (這種老舊協(xié)議)不支持它一點都會不意外。

設(shè)置 proxy_http_version 1.1 從而解決那個麻煩。好欸!

問題二:事件被緩沖

這個事情解決完,第二個麻煩接踵而至。不過這個問題實際上非常好解決,因為 Cass 已經(jīng)建議將 stackoverflow 里另一篇帖的回答 作為前一個問題的解決方案,雖然它并沒有是導(dǎo)致問題一出現(xiàn)的源頭,但它-確-實-解-釋-了問題二。

問題在這個示例代碼中:

def handler
    response.headers['Content-Type'] = 'text/event-stream'
    # Turn off buffering in nginx
    response.headers['X-Accel-Buffering'] = 'no'
    sse = SSE.new(response.stream, event: "status")
    10.times do
        sse.write('event')
        sleep 1
    end
end

我本來期望它每秒返回 1 個事件,持續(xù) 10 秒,但實際上它等了 10 秒才把 10 個事件一起返回。這不是我們想要的流式傳輸方式!

原來這是因為 Rack ETag 中間件想要計算 ETag(響應(yīng)的哈希值),為此它需要整個響應(yīng)為它服務(wù)。因此,我需要禁用 ETag 生成。

Stack Overflow 的回答建議完全禁用 Rack ETag 中間件,但我不想這樣做,于是我去看了 鏈接至 GitHub 上的議題。

那個 GitHub 議題建議我可以針對僅流式傳輸終端應(yīng)用一個解決方法,即 Last-Modified 響應(yīng)頭,顯然,這么做可以繞過 ETag 中間件。

所以我設(shè)置為:

headers['Last-Modified'] = Time.now.httpdate

然后它起作用了?。?!

我還通過設(shè)置響應(yīng)頭 X-Accel-Buffering: no 關(guān)閉了位于 Nginx 中的緩沖區(qū)。我并沒有百分百確定我要那樣做,但這么做似乎更安全。

Stack Overflow 很棒

起初,我全身心致力于從頭開始調(diào)試這兩個錯誤。Cass 為我指向了那兩個 Stack Overflow 帖子,一開始我對那些帖下提出的解決方案持懷疑態(tài)度(我想:“我沒有使用 HTTP/1.0 ?。Tag 響應(yīng)頭什么玩意,跟這一切有關(guān)系嗎??”)。

但結(jié)果證明,我確實無意中使用  HTTP/1.0,并且 Rack ETag 中間件確實給我?guī)砹藛栴}。

因此,也許這個故事告訴我,有時候計算機(jī)就是會以奇怪的方式相互作用,其它人在過去也遇到過計算機(jī)以完全相同的奇怪方式相互作用的問題,而 Stack Overflow 有時會提供關(guān)于為什么會發(fā)生這些情況的答案 : )

我認(rèn)為重要的是不要隨意從 Stack Overflow 中嘗試各種解決方案(當(dāng)然,在這種情況下不會有人建議這樣做?。?。對于這兩個問題,我確實需要去仔細(xì)思考,了解發(fā)生了什么,還有為什么更改這些設(shè)置會起作用。

就是這樣!

今天我要繼續(xù)著手實現(xiàn)服務(wù)器推送事件,因為昨天一整天我都沉浸在上述這些錯誤里。好在我學(xué)到了一個以前從未聽說過的易學(xué)易用的網(wǎng)絡(luò)技術(shù),心里還是很高興的。


網(wǎng)站欄目:服務(wù)器推送事件:一種從服務(wù)器流式推送事件的簡易方法
網(wǎng)站URL:http://www.5511xx.com/article/ccodpeh.html