我一直在使用 CouchDB 和 Golang 遇到一個棘手的問題。當向 CouchDB 發送具有相對較大 Body 大小的 POST/PUT 請求(閾值似乎約為 8000 字節左右)時,連接超時并且我從 Go 收到“tcp:使用關閉的網絡連接”錯誤。最終(一兩秒后),CouchDB 發送一個 500 響應以及:{"error":"unknown_error", "reason": "noproc"}在身體里。couchdb 日志還寫入了一個堆棧跟蹤:Stacktrace: [{couch_db,collect_results,3, [{file,"couch_db.erl"},{line,833}]}, {couch_db,write_and_commit,4, [{file,"couch_db.erl"},{line,845}]}, {couch_db,update_docs,4, [{file,"couch_db.erl"},{line,782}]}, {couch_db,update_doc,4, [{file,"couch_db.erl"},{line,426}]}, {couch_httpd_db,update_doc,6, [{file,"couch_httpd_db.erl"},{line,753}]}, {couch_httpd_db,do_db_req,2, [{file,"couch_httpd_db.erl"},{line,234}]}, {couch_httpd,handle_request_int,5, [{file,"couch_httpd.erl"},{line,318}]}, {mochiweb_http,headers,5, [{file,"mochiweb_http.erl"},{line,94}]}]所以我寫了一個快速的單元測試來復制這個問題(并確保它不是我的包裝導致問題)。我正在提出這樣的請求:client := &http.Client{}req, err := http.NewRequest( "PUT", "http://localhost:5984/unittestdb/testdocid1", bytes.NewReader(testBody1), //testBody1 is 10000 bytes of json object)req.Header.Set("Content-Type", "application/json")req.Header.Set("Accept", "application/json")resp, err := client.Do(req)這復制了這個問題......所以我嘗試將一個大的json文檔卷曲到couchdb。 那奏效了。因此,我啟動了wireshark并檢查了我的代碼向CouchDB發出的請求,并將其與curl發送的請求進行了比較。我注意到 Curl 請求中有一個額外的標頭:Expect: 100-continue我不得不查一下那個,因為我不記得以前看過(或者我可能只是沒有處理過)那個標題。于是我google了一下Golang的http客戶端是否支持Expect/Continue功能,結果發現:https : //github.com/golang/go/issues/3665所以 Go 不支持它,至少在 1.6 之前不會。所以我認為這一定是一件晦澀的事情,而不是我的問題的根源。我花了幾個小時隨機嘗試使用 http.Client、Transport 等其他東西。最終,我在 Go 中的 http 請求中手動設置了“Expect: 100-continue”標頭(如果主體尺寸超過特定尺寸),并且......它起作用了。沒有超時,沒有錯誤,沒有 couchdb 將堆棧跟蹤記錄到日志中?,F在我很困惑,如果 Go 不支持這個,它是如何工作的?我這樣做只是掩蓋了問題嗎?或者我可以聳聳肩繼續前進嗎?我懷疑 CouchDB 方面存在問題,也許我缺少配置設置?
1 回答

幕布斯6054654
TA貢獻1876條經驗 獲得超7個贊
我不知道答案,但我認為您的關鍵規范是RFC 2616 section 8.2.3。整個部分很有趣,但特別是這個:
“此規則有一個例外:為了與 RFC 2068 兼容,服務器可以發送 100(繼續)狀態以響應 HTTP/1.1 PUT 或 POST 請求,該請求不包含帶有“100 -continue”期望。此異常的目的是最小化與未聲明的等待 100(繼續)狀態相關的任何客戶端處理延遲,僅適用于 HTTP/1.1 請求,而不適用于具有任何其他 HTTP 版本值的請求.”
聽起來你被 Go 缺少的 100-continue 實現和 CouchDB 方面的某種極端情況所困擾。(無論客戶端的行為如何,我都不認為 500 Internal error 是來自服務器的適當響應。)
如果 Go 客戶端允許您設置,我會嘗試使用 HTTP/1.0 作為解決方法。
- 1 回答
- 0 關注
- 312 瀏覽
添加回答
舉報
0/150
提交
取消