node.js - 使用 node.js http2 模块的服务器发送事件 - 我应该如何将它与流/pushStream 一起使用?

标签 node.js stream server-sent-events http2

我正在尝试实现每 500 毫秒发送大量数据(对象,而不是文件)的服务器。
经过一番阅读,服务器通过 http2 发送的事件似乎是最快的选择(由于 http2 是二进制协议(protocol),SSE 减少了流量开销)

玩了一下SSE在 http/1.1
我一直在尝试在 http2 上做同样的事情。我试过用 stream 这样做和 pushStream ,但没有成功。但是,使用与 http/1.1 相同的方式似乎可行。

我的问题是 - 为什么使用流的服务器 1(见下文)不起作用,而服务器 2 似乎工作正常?工作 Node 流时我错过了什么吗?

我正在使用 Node v10.9.0和 Chrome 68.0.3440.106
我已阅读以下问题和帖子,但仍然无法解决此问题:

  • Can I stream a response back to the browser using http2?
  • Node.js HTTP2 server Error: socket hang up
  • HTTP2 / SPDY Push-Stream Verification: How to Test?
  • HTTP/2 Server Push with Node.js
  • Using Server Sent Events with express

  • 服务器 1 - 带有流的 http2(不工作 - 客户端没有收到事件。chrome 将请求描述为未完成的请求):
    const fs = require('fs');
    const http2 = require('http2');
    
    const HTTPSoptions = {
        key: fs.readFileSync('./cert/selfsigned.key'),
        cert: fs.readFileSync('./cert/selfsigned.crt'),
    };
    const template = `
    <!DOCTYPE html> 
    <html>
    <body>
        <script type="text/javascript">
            const  source = new EventSource('/sse/');
            source.onmessage = function(e) { 
                document.body.innerHTML += e.data + '<br>';
            };
        </script>
    </body>
    </html>
    `;
    
    
    const server = http2.createSecureServer(HTTPSoptions);
    
    server.on('stream', (stream, headers, flags) => {
        if (stream.url === 'sse/') {
            console.log(stream.respond);
            stream.respond({
                ':status': 200,
                'content-type': 'text/event-stream'
            });
            setInterval(() => stream ? res.write(`data: ${Math.random()}\n\n`) : '', 200);
        }
    });
    
    server.on('request', (req, res) => {
        if(req.url === '/') {
            res.end(template);
        }
    });
    
    
    
    server.listen(3001);
    

    服务器 2 - 带有流的 http2(工作正常):
    const fs = require('fs');
    const http2 = require('http2');
    
    const HTTPSoptions = {
        key: fs.readFileSync('./cert/selfsigned.key'),
        cert: fs.readFileSync('./cert/selfsigned.crt'),
    };
    const template = `
    <!DOCTYPE html> 
    <html>
    <body>
        <script type="text/javascript">
            const  source = new EventSource('/sse/');
            source.onmessage = function(e) { 
                document.body.innerHTML += e.data + '<br>';
            };
        </script>
    </body>
    </html>
    `;
    
    
    const server = http2.createSecureServer(HTTPSoptions);
    
    server.on('request', (req, res) => {
        req.socket.setKeepAlive(true);
    
        if(req.url === '/sse/') {
    
            res.writeHead(200, {
                'Content-Type': 'text/event-stream', // <- Important headers
                'Cache-Control': 'no-cache'
            });
            res.write('\n');
    
            setInterval(() => res.write(`data: ${Math.random()}\n\n`), 200);
        } else {
            res.end(template);
        }
    });
    
    server.listen(3001);
    

    最佳答案

    要获取 http2 流的请求路径,您必须查看 :path header (docs):

    if (headers[':path'] === '/sse/') {
    

    您还尝试使用 res.write , 而 res应该是 stream .

    这是一个基于您的“服务器 1”实现的工作处理程序函数:

    server.on('stream', (stream, headers, flags) => {
        if (headers[':path'] === '/sse/') {
            stream.respond({
                ':status': 200,
                'content-type': 'text/event-stream'
            });
            setInterval(() => stream.write(`data: ${Math.random()}\n\n`), 200);
        }
    });
    

    关于node.js - 使用 node.js http2 模块的服务器发送事件 - 我应该如何将它与流/pushStream 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52086683/

    相关文章:

    node.js - 如何使用 list Node.js 站点进行缓存

    ruby-on-rails - 如何在rails 3中实时推送内容

    javascript - SSE(服务器发送事件)断开连接

    audio - 如何解决 PJSIP 中接收音频 RTP 流(音质差)时的 Jitter Buffer 问题?

    html - 3-4 秒后收到服务器发送的事件

    node.js - 环回引用许多嵌套外键

    node.js - 使用 NodeJS 的 WooCommerce API 添加了不完整的产品变体

    javascript - Node JS 路由 URL 冲突

    java - Apache 耶拿 - java.lang.UnsupportedClassVersionError : com/hp/hpl/jena/rdf/model/ModelFactory

    c# - 文件 I/O 最佳实践 - byte[] 还是 FileStream?