保持活动请求 _change 连续供稿

我正在尝试将以下 nodejs 代码转换为 Go。我必须向 PouchDB 服务器的 _changes?feed=continuous 建立保持活动 http 请求。但是,我无法在 Go 中实现它。


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();

下面是围棋代码


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 好的,但没有打印数据,它卡住了。另一方面,如果我使用 longpoll 选项,即。http://localhost:3030/downloads/_changes?feed=longpoll然后我正在接收数据。


慕丝7291255
浏览 113回答 2
2回答

长风秋雁

您的代码“按预期”运行,并且您在 Go 中编写的内容并不等同于 Node.js 中显示的代码。继续执行代码块,ioutil.ReadAll(resp.Body)因为连接由 CouchDB 服务器保持打开状态。一旦服务器关闭连接,您的客户端代码将打印出来result,ioutil.ReadAll()以便能够将所有数据读取到 EOF。从CouchDB 文档中关于连续馈送:连续提要保持打开并连接到数据库,直到明确关闭,并且在发生更改时将其发送给客户端,即近乎实时的。与 longpoll 提要类型一样,您可以设置超时和心跳间隔,以确保连接保持打开状态以进行新的更改和更新。您可以尝试实验并添加&timeout=1到 URL,这将强制 CouchDB 在 1 秒后关闭连接。然后你的 Go 代码应该打印整个响应。Node.js 代码的工作方式不同,data每次服务器发送一些数据时都会调用事件处理程序。如果您想实现相同并处理部分更新(在连接关闭之前),则不能使用ioutil.ReadAll()因为它等待 EOF(因此在您的情况下会阻塞),但类似于resp.Body.Read()处理部分缓冲区。这是一个非常简化的代码片段,它演示了这一点,应该给你基本的想法:package mainimport (    "fmt"    "net/http"    "net/url"    "strings")func main() {    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)    defer resp.Body.Close()    fmt.Println(resp.Status)    if err != nil {        fmt.Println(err)    }    buf := make([]byte, 1024)    for {        l, err := resp.Body.Read(buf)        if l == 0 && err != nil {            break // this is super simplified        }        // here you can send off data to e.g. channel or start        // handler goroutine...        fmt.Printf("%s", buf[:l])    }    fmt.Println()}在现实世界的应用程序中,您可能希望确保您buf持有看起来像有效消息的内容,然后将其传递给通道或处理程序 goroutine 以进行进一步处理。

慕运维8079593

最后,我能够解决这个问题。该问题与DisableCompression标志有关。https://github.com/golang/go/issues/16488这个问题给了我一些提示。通过设置DisableCompression: true解决了这个问题。client := &http.Client{Transport: &http.Transport{    DisableCompression: true, }}我假设默认client := &http.Client{}发送DisableCompression : false并且 pouchdb 服务器正在发送压缩的 json,因此接收到的数据被压缩并且 resp.Body.Read 无法读取。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go