Http 来自Go to CouchDB的大型PUT请求
我和CouchDB和Golang之间一直有个棘手的问题。当发送POST/PUT请求到具有相对较大正文大小(阈值似乎约为8000字节)的CouchDB时,连接超时,我从Go收到一个“tcp:use of closed network connection”错误 最终(一两秒钟后),CouchDB会发送一个500响应和一个:Http 来自Go to CouchDB的大型PUT请求,http,go,couchdb,Http,Go,Couchdb,我和CouchDB和Golang之间一直有个棘手的问题。当发送POST/PUT请求到具有相对较大正文大小(阈值似乎约为8000字节)的CouchDB时,连接超时,我从Go收到一个“tcp:use of closed network connection”错误 最终(一两秒钟后),CouchDB会发送一个500响应和一个: {"error":"unknown_error", "reason": "noproc"} 在身体里。couchdb日志中还写入了堆栈跟踪: Stacktrace: [{co
{"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功能,结果发现:
所以Go不支持它,至少在1.6之前不会支持它。所以我认为这一定是一件晦涩难懂的事情,不是我问题的根源。我花了几个小时随机尝试了http、客户端、传输等其他东西
最后,我在Go中手动设置http请求中的“Expect:100 continue”头(如果正文大小超过某个大小),然后。。。成功了。没有超时,没有错误,没有couchdb将堆栈跟踪加载到日志中
现在我很困惑,如果Go不支持这个,它是如何工作的?我这样做只是为了掩盖问题吗?还是我可以耸耸肩继续前行
我怀疑CouchDB方面存在问题,也许我缺少一个配置设置?我不知道答案,但我认为您的关键规范是。整个部分都很有趣,但特别是: “此规则有一个例外:为了与RFC 2068兼容, 服务器可以发送100(继续)状态以响应HTTP/1.1 不包含Expect请求标头的PUT或POST请求 字段中包含“100 continue”期望值。此异常为 其中之一是最大限度地减少与 未声明的等待100(继续)状态仅适用于HTTP/1.1 请求,而不是具有任何其他HTTP版本值的请求。“ 这听起来像是你被夹在Go缺少的100 continue实现和CouchDB端的一些角落案例之间。(无论客户端的行为如何,我认为500内部错误都不是来自服务器的适当响应。)
如果Go客户端允许您设置,我会尝试使用HTTP/1.0作为解决方法。如果CouchDB“将堆栈跟踪添加到日志中”,那么您应该将它们添加到问题中。好的,添加了堆栈跟踪。如果重要的话,我正在FreeBSD 10.1:)上运行CouchDB 1.6.1和Go 1.4.1。不幸的是,Go客户端请求总是使用HTTP/1.1