我一直在使用 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 将堆栈跟踪记录到日志中。现在我很困惑,如果 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 关注
- 269 浏览
添加回答
举报
0/150
提交
取消