使用Node.js的http2模块实现服务器推送事件 - 我应该如何在流/ pushStream中使用它?

5
我正在尝试实现一个服务器,每500毫秒发送大量数据(对象而非文件)。经过一些阅读,通过HTTP2的服务器发送事件似乎是最快的选项(由于HTTP2是二进制协议,SSE减少了流量开销)。
在http/1.1上使用SSE进行了一些尝试后,我一直在尝试在http2上做同样的事情。我尝试使用streampushStream来实现,但没有成功。然而,使用我在http/1.1上使用的相同方法似乎可以工作。
我的问题是 - 为什么使用流的服务器1(见下文)不起作用,而服务器2似乎正常工作?当使用节点流时,是否有遗漏?
我正在使用node v10.9.0和chrome 68.0.3440.106

我已经阅读了以下问题和帖子,但仍然无法解决此问题:

服务器1 - http2 with stream(不工作-客户端未收到事件。谷歌将请求描述为未完成的请求):

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);
1个回答

3
要获取 HTTP2 流的请求路径,您需要查看 :path 标头 (文档)。
if (headers[':path'] === '/sse/') {

你也尝试使用了res.write,然而正确应该使用stream.write
以下是基于你的“Server 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);
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接