Http 保持活动状态请求更改连续馈送
我正在尝试将下面的nodejs代码转换为Go。我必须建立keep-alive http请求来保存数据库服务器的_changes?feed=continuous。然而,我无法在围棋中实现它Http 保持活动状态请求更改连续馈送,http,go,couchdb,keep-alive,Http,Go,Couchdb,Keep Alive,我正在尝试将下面的nodejs代码转换为Go。我必须建立keep-alive http请求来保存数据库服务器的_changes?feed=continuous。然而,我无法在围棋中实现它 var http = require('http') var agent = new http.Agent({ keepAlive: true }); var options = { host: 'localhost', port: '3030', method: 'GET',
var http = require('http')
var agent = new http.Agent({
keepAlive: true
});
var options = {
host: 'localhost',
port: '3030',
method: 'GET',
path: '/downloads/_changes?feed=continuous&include_docs=true',
agent
};
var req = http.request(options, function(response) {
response.on('data', function(data) {
let val = data.toString()
if(val == '\n')
console.log('newline')
else {
console.log(JSON.parse(val))
//to close the connection
//agent.destroy()
}
});
response.on('end', function() {
// Data received completely.
console.log('end');
});
response.on('error', function(err) {
console.log(err)
})
});
req.end();
下面是Go代码
client := &http.Client{}
data := url.Values{}
req, err := http.NewRequest("GET", "http://localhost:3030/downloads/_changes?feed=continuous&include_docs=true", strings.NewReader(data.Encode()))
req.Header.Set("Connection", "keep-alive")
resp, err := client.Do(req)
fmt.Println(resp.Status)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
我的状态是200 Ok,但是没有数据被打印出来,它被卡住了。另一方面,如果我使用longpoll选项ie,那么我正在接收数据。您的代码“按预期”工作,并且您在Go中编写的代码与Node.js中显示的代码不等效。转到ioutil.ReadAll(resp.Body)
上的代码块,因为CouchDB服务器保持连接打开。一旦服务器关闭连接,您的客户端代码将打印出result
作为ioutil.ReadAll()
将能够读取到EOF的所有数据
关于连续进纸:
连续提要保持打开并连接到数据库,直到显式关闭,并在发生更改时(即近实时)将更改发送到客户端。与longpoll提要类型一样,您可以设置超时和心跳间隔,以确保连接保持打开状态,以便进行新的更改和更新
您可以尝试在URL中添加&timeout=1
,这将强制CouchDB在1s后关闭连接。然后,您的Go代码应该打印整个响应
Node.js代码的工作方式不同,每次服务器发送数据时都会调用事件数据处理程序。如果您希望实现相同的更新并处理部分更新(在连接关闭之前),则不能使用as等待EOF(因此在您的情况下会阻塞),而是使用类似resp.Body.Read()
的方法来处理部分缓冲区。下面是一段非常简单的代码片段,它演示了这一点,并应为您提供基本的想法:
主程序包
进口(
“fmt”
“net/http”
“网络/网址”
“字符串”
)
func main(){
客户端:=&http.client{}
数据:=url.Values{}
req,err:=http.NewRequest(“GET”http://localhost:3030/downloads/_changes?feed=continuous&include_docs=true,strings.NewReader(data.Encode()))
请求标题集(“连接”,“保持活动”)
resp,err:=client.Do(请求)
延迟响应主体关闭()
fmt打印LN(各自状态)
如果错误!=零{
fmt.Println(错误)
}
buf:=make([]字节,1024)
为了{
l、 错误:=分别读取正文(buf)
如果l==0&&err!=nil{
中断//这是超级简化
}
//在这里,您可以将数据发送到例如channel或start
//处理程序goroutine。。。
fmt.Printf(“%s”,buf[:l])
}
fmt.Println()
}
在现实世界的应用程序中,您可能希望确保您的buf
包含看起来像有效消息的内容,然后将其传递给通道或处理程序goroutine进行进一步处理。最后,我能够解决此问题。该问题与DisableCompression
标志有关。这个问题给了我一些提示
通过设置DisableCompression:true
修复了该问题。
client:=&http.client{Transport:&http.Transport{
DisableCompression:对,
}}
我假设默认情况下,client:=&http.client{}
发送DisableCompression:false
,PockDB服务器发送压缩的json,因此接收到的数据被压缩,resp.Body.Read无法读取。嗨,我以前尝试过resp.Body.Read,但没有成功。不过,我还是按照你的建议再试了一次,但没有成功。另一方面,nodejs代码可以完美地工作fine@Pram“不工作”是指它仍然无限期地阻塞吗?@Pram只是澄清一下,使用我的代码片段,它没有打印任何数据和阻塞,或者你看到数据通过它然后阻塞了吗?我没有看到任何由fmt.Printf(“%s”,buf[:l])打印的数据在allI编辑了我的答案,并发布了最小的完整文件可执行示例以进行分类。我刚刚在Docker中对本地运行的CouchDB进行了测试,它的行为与Node.js代码相同(应该打印出一些数据,然后阻塞)。如果这个在你的Env中工作得很好,那么你的代码中还有其他的问题。你应该考虑使用一个库来为你做这项工作。在那里,@Flimzy我曾使用过Kivik,但我面临着类似的问题。因此决定直接与couchdb沟通。谢谢你的链接。这个问题看起来和你在这里描述的完全不同。无论如何,我用一些建议回答了你的Kivik问题。非常抱歉,我使用的是PockDB,我认为API是类似的。因此提到couchDb.API是相似的,但它们的底层功能完全不同。PockDB完全在浏览器中运行,CouchDB在服务器上运行。