Pipe
使用 Unix 管道將數據流式傳輸到 REST 服務
根據對另一個問題的回答,我正在使用 curl 將
stdout
一個程序的流式傳輸作為POST
請求的實體:myDataGeneratingApp \ | curl -H "Content-Type: application/json" -H "Transfer-Encoding: chunked" -X POST -d @- http://localhost:12000
EOF
不幸的是,curl在開始發送數據之前正在等待標準輸出。我知道這一點是因為我可以獨立執行我的應用程序,並且數據會立即輸出到控制台,但是當我通過管道進行 curl 時,在服務開始接收數據之前會有很大的延遲。當數據從應用程序的標準中可用時,如何使用 curl 立即流式傳輸數據?如果在 curl 中不可能,那麼是否有另一種解決方案(例如 wget)?
查看 curl 程式碼transfer.c似乎該程序能夠使用分塊協議重新打包請求數據(從 curl 到伺服器),其中每個數據塊都以 ascii 十六進制的塊長度為前綴,並以由
\r\n
.在連接到伺服器後,似乎讓它以流的方式使用它的方法是使用
-T -
. 考慮這個例子:for i in $(seq 5) do date sleep 1 done | dd conv=block cbs=512 | strace -t -e sendto,read -o /tmp/e \ curl --trace-ascii - \ -H "Transfer-Encoding: chunked" \ -H "Content-Type: application/json" \ -X POST -T - http://localhost/...
此腳本將 5 個數據塊發送到一個管道,每個數據塊都以日期開頭並由 填充到 512 個字節
dd
,在該管道中strace
執行curl -T -
以讀取管道。在終端中我們可以看到== Info: Connected to localhost (::1) port 80 (#0) => Send header, 169 bytes (0xa9) 0000: POST /... HTTP/1.1 001e: Host: localhost 002f: User-Agent: curl/7.47.1 0048: Accept: */* 0055: Transfer-Encoding: chunked 0071: Content-Type: application/json 0091: Expect: 100-continue 00a7: <= Recv header, 23 bytes (0x17) 0000: HTTP/1.1 100 Continue
它顯示了連接和發送的標頭。特別是
curl
沒有提供Content-length:
標頭,而是Expect:
伺服器(apache)已回复的標頭Continue
。緊隨其後的是數據的前 512 個字節(200 十六進制):=> Send data, 519 bytes (0x207) 0000: 200 0005: Fri Sep 14 15:58:15 CEST 2018 0045: 0085: 00c5: 0105: 0145: 0185: 01c5: => Send data, 519 bytes (0x207)
查看
strace
輸出文件,我們看到管道中的每個時間戳read
,並sendto
寫入連接:16:00:00 read(0, "Fri Sep 14 16:00:00 CEST 2018 "..., 16372) = 512 16:00:00 sendto(3, "200\r\nFri Sep 14 16:00:00 CEST 20"..., 519, ...) = 519 16:00:00 read(0, "Fri Sep 14 16:00:01 CEST 2018 "..., 16372) = 512 16:00:01 sendto(3, "200\r\nFri Sep 14 16:00:01 CEST 20"..., 519, ...) = 519 16:00:01 read(0, "Fri Sep 14 16:00:02 CEST 2018 "..., 16372) = 512 16:00:02 sendto(3, "200\r\nFri Sep 14 16:00:02 CEST 20"..., 519, ...) = 519 16:00:02 read(0, "Fri Sep 14 16:00:03 CEST 2018 "..., 16372) = 512 16:00:03 sendto(3, "200\r\nFri Sep 14 16:00:03 CEST 20"..., 519, ...) = 519 16:00:03 read(0, "Fri Sep 14 16:00:04 CEST 2018 "..., 16372) = 512 16:00:04 sendto(3, "200\r\nFri Sep 14 16:00:04 CEST 20"..., 519, ...) = 519 16:00:04 read(0, "", 16372) = 0 16:00:05 sendto(3, "0\r\n\r\n", 5, ...) = 5
如您所見,它們間隔 1 秒,表明數據在接收時正在發送。您必須至少有 512 個字節要發送,因為數據正在被
fread()
.