每次需求里蹦出“實時”兩個字——一個在線計數器、一個小綠點“在線”、一條“新消息”角標、一個動態信息流——大家的第一反應總是沖進依賴里拖一個WebSocket服務出來。Pusher、Ably、Socket.IO服務器,或者在你那無狀態應用旁邊再掛一個有狀態的Node進程。這套組合拳等于憑空多出一個要部署、要擴容、要運維、要花錢的東西,而它大部分時間只是在把幾條雞毛蒜皮的事件從一個地方挪給一堆瀏覽器。
其實你的數據既然已經躺在Postgres里,你就已經有了一條現成的消息總線。Postgres自帶一對輕量級的發布/訂閱原語:LISTEN和NOTIFY。把它跟Server-Sent Events(SSE)搭配在一起,再用一個無服務器函數把兩邊串起來,就能把實時更新扇出給每一個連接著的客戶端,全程不用額外架設任何實時基礎設施。接下來我就用Neon Function搭了這么一套,解釋一下它在無服務器環境里唯一需要留神的那一個坑,并且用兩個在線訂閱者證明方案跑得通。代碼倉庫放在最后。
![]()
先拆成兩部分看:
Postgres的LISTEN/NOTIFY是內建在數據庫里的一個發布/訂閱頻道。一個連接執行LISTEN counter_updates之后,任何一個連接——哪怕來自完全不同的地方——只要執行NOTIFY counter_updates, '42',Postgres就會把那條負載推給所有訂閱了這個頻道的連接。沒有額外服務,不用再跑一個消息中間件,這就是你本來就在用的數據庫的自帶功能。
Server-Sent Events (SSE) 是另一半拼圖。SSE本質上是一個長生命周期的HTTP響應,持續向瀏覽器推送數據幀,客戶端用瀏覽器內置的EventSource API就能直接消費。它是單向的(服務器到客戶端),而這恰好就是絕大多數實時UI的需求形態:服務器手里有新鮮事,瀏覽器想知道。更妙的是,既然它只是個HTTP響應,一個無服務器函數就能直接提供。
把兩者捏在一起就成了:函數一邊把SSE流推給瀏覽器,一邊轉發從Postgres頻道里聽到的任何動靜。
在無服務器環境下最容易踩的坑其實一句話就能說清楚:函數在壓力下不會只跑在一個進程里,運行時會并行啟動好幾個隔離實例。每個隔離實例都在內存里維護著自己那一份客戶端列表,如果只是進程內做廣播,你的消息最多只能扇到當前隔離實例關聯的那部分客戶端,另一半等著收消息的用戶根本不會收到。這時候LISTEN/NOTIFY就成了救星,它有本事把一條事件扇到所有隔離實例上:每個隔離實例都保持著一條對Postgres的LISTEN長連接,只要有一個寫操作調用了pg_notify,Postgres就會把事件推到每一個正在LISTEN的隔離實例上,各個隔離實例再分別把它扇給自己的SSE客戶端,誰也不會被落下。
五個你必須知道的硬核要點,否則你就會在半夜被報警叫醒:
1. LISTEN需要的是一個會話級別的連接,千萬別用事務連接池,必須老老實實走直連(unpooled connection),不然你根本等不到任何通知。
2. 這套方案是對小型實時事件的扇出,不是持久化的消息隊列。它不保證投遞,連接斷掉的客戶端就該丟的消息還是會丟。
3. 如果你的場景要求投遞保證,或者需要低延遲的雙向通信,那WebSocket或正經的消息中間件依然是更合適的選擇,別硬套。
4. 每個在無服務器函數里維護的SSE連接都是一個長連接,這意味著函數實例不會輕易被回收,請根據實際承受能力評估并發的數據庫連接數。
5. pg_notify的payload就是個純文本,你塞進去的內容長度有上限(默認8000字節),別幻想把它當成對象存儲來用。
提前準備的東西沒幾樣:一個Neon平臺預覽版的項目(需要用到Functions,目前是在us-east-2區域),把Neon命令行工具裝好(npm i -g neon之后執行neon login),然后你只需要對Postgres和瀏覽器端的SSE/EventSource有基本了解就行。就這些。
你可能會覺得這太樸素了,連個花哨的中間件都沒用。可它的優雅正在于這一點:拿掉一切不必要的層,把數據庫里被低估的內置能力拎出來當實時通道用,讓無服務器函數只專注在一件小事上——接住SSE,把通知撒下去。下一次產品經理走過來跟你聊實時需求時,你不妨先反問一句:“我們有必要為這東西單獨部署一套服務嗎?” 也許答案真的沒你想的那么理所當然。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.