apisix~對sse事(shi)件流(liu)的(de)支(zhi)持~api7.ai的(de)方(fang)案
-
企業級中有proxy-buffer插(cha)件,說是可(ke)以支持sse
在 APISIX 中,如果你需要關閉 Nginx 的緩沖區以支持 SSE(Server-Sent Events)的 text/event-stream 響應(ying),確保(bao)數據(ju)能夠實時流式傳輸(shu)到客戶(hu)端,可以通過以下步驟實現。
1. 禁用 Nginx 的代理緩沖
Nginx 默認會啟用代理緩沖(proxy_buffering),這會導(dao)致(zhi) SSE 數(shu)據被緩(huan)存并(bing)按(an)塊返回,而不是實時流式傳輸。為了禁用緩(huan)沖,需要(yao)修改 Nginx 的(de)配置(zhi)。
修改 APISIX 的 Nginx 配置文件
APISIX 是基(ji)于 Nginx 的(de),因此可以(yi)通過(guo)修改 APISIX 的(de) Nginx 配置文件(jian)來(lai)禁用(yong)緩沖。
-
打開(kai) APISIX 的 Nginx 配置文件模(mo)板:
- 文件路徑通常為
/usr/local/apisix/conf/nginx.conf。 - 如果你使用了自定義的 Nginx 模板,路徑可能不同。
- 文件路徑通常為
-
在
http塊(kuai)中添(tian)加(jia)全(quan)局配置:http { proxy_buffering off; # 禁用代理緩沖 proxy_buffer_size 1k; # 設置緩沖區大小為 1KB proxy_buffers 4 1k; # 設置緩沖區數量和大小 }proxy_buffering off:完全禁用代理緩沖,確保數據實時傳輸。proxy_buffer_size和proxy_buffers:將緩沖區大小設置為較小的值(如 1KB),以減少數據分塊的大小。
加到某個server下面
server {
listen 80;
server_name app1.example.com;
# 覆蓋全局配置:關閉本server所有請求的代理緩沖
proxy_buffering off; # ? 生效層級:當前server
}
** apisix的(de)helm版的(de)values.yaml配置
nginx:
# 支持sse的事件流協議text/event-stream,在插件中為上游顯示的添加了X-Accel-Buffering為no,這時當前apisix的nginx相當于走了proxy_buffering為off的特性
http_server_location_configuration_snippet: |
proxy_buffering on;
- 保存文件并重啟 APISIX:
apisix restart
2. 在路由中禁用緩沖
除了全局禁用緩沖,還可以在特定路由中禁用緩沖。通過 proxy-rewrite 插件的 disable_buffering 參數實現。
示例配置
{
"uri": "/your-sse-endpoint",
"plugins": {
"proxy-rewrite": {
"disable_buffering": true # 禁用緩沖
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"your-backend-service:80": 1
}
}
}
disable_buffering: true:確保該路由的響應數據不會被緩沖。
3. 調整 Nginx 的 chunked_transfer_encoding
確保 Nginx 啟用了分塊傳輸編碼(chunked_transfer_encoding),這是(shi) SSE 流(liu)式傳輸(shu)的基礎(chu)。
在 Nginx 配置中(zhong)添(tian)加以下內(nei)容:
http {
chunked_transfer_encoding on; # 啟用分塊傳輸編碼
}
4. 檢查后端服務的響應頭
確保后端服務返回的響應頭中沒有 Content-Length,并且啟用了分塊傳輸編碼(Transfer-Encoding: chunked)。SSE 是流(liu)式協(xie)議(yi),響應應該是分塊(kuai)傳輸的。
檢(jian)查后(hou)端服務的響(xiang)應頭,確保(bao)如下:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Transfer-Encoding: chunked
Connection: keep-alive
如果后端服務返回了 Content-Length,Nginx 可能會根據該長度進行(xing)緩沖。
5. 使用 Lua 腳本自定義流式處理
如果以上方法(fa)仍(reng)然無(wu)法(fa)滿足需求,可以通過(guo) Lua 腳本自定義流(liu)式處理邏輯(ji),確保數(shu)據逐字轉發。
示例 Lua 腳本
local core = require("apisix.core")
local ngx = ngx
local function逐字轉發()
-- 設置響應頭
ngx.header["Content-Type"] = "text/event-stream"
ngx.header["Cache-Control"] = "no-cache"
ngx.header["Connection"] = "keep-alive"
-- 連接后端服務
local sock = ngx.socket.tcp()
local ok, err = sock:connect("your-backend-service", 80)
if not ok then
core.log.error("failed to connect to backend: ", err)
return ngx.exit(500)
end
-- 逐字讀取并轉發
while true do
local byte, err = sock:receive(1) -- 每次讀取 1 字節
if not byte then
break
end
ngx.print(byte) -- 逐字轉發
ngx.flush(true) -- 立即刷新緩沖區
end
-- 關閉連接
sock:close()
end
return逐字轉發
在路由中應用 Lua 腳本
通過 serverless-pre-function 插件加載 Lua 腳本:
{
"uri": "/your-sse-endpoint",
"plugins": {
"serverless-pre-function": {
"phase": "access",
"functions": [
"local function逐字轉發 = require('sse_stream') 逐字轉發()"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"your-backend-service:80": 1
}
}
}
6. 測試
完成(cheng)配置后,通過以下方式測試 SSE 數據是(shi)否(fou)實(shi)時(shi)流(liu)式傳輸:
-
使用
curl測試:curl -N //<APISIX-IP>:<APISIX-PORT>/your-sse-endpoint -
在瀏覽器中測試:
打開開發者工(gong)具(ju),查(cha)看 SSE 數據是否實時接收。
總結
要關閉 Nginx 的緩沖區以支持 SSE 的 text/event-stream 響應,可以:
- 在 Nginx 配置中禁用代理緩沖(
proxy_buffering off)。 - 在路由中設置
disable_buffering: true。 - 確保后端服務返回分塊傳輸編碼(
Transfer-Encoding: chunked)。 - 如果需要更精細的控制,可以使用 Lua 腳本自定義流式處理邏輯。
通過這(zhe)些方法,可以確保 SSE 數據(ju)實(shi)時(shi)流式傳輸到(dao)客戶(hu)端(duan)。