了解如何将Redis与Node.js和服务器发送事件一起使用

时间:2016-09-19 08:40:12

标签: javascript node.js heroku redis server-sent-events

My Project是使用Nodejs作为代理服务器构建的,用于与外部API通信。

API通过Redis(pub / sub)发送产品更新;代理服务器处理消息并通过SSE(服务器发送事件)将其发送到客户端。

这是我第一次使用Redis和SSE,在线查看教程似乎很容易实现,我做到了。

在客户端,我刚刚创建了一个EventSource,我收到更新后立即对其进行了处理:

// Client Side
var source = new EventSource('/redis'); // /redis is path to proxy server
source.addEventListener('items', handleItemsCallback, false);
source.addEventListener('users', handleUsersCallback, false);
source.addEventListener('customers', handleCustomersCallback, false);

// Function sample...
function handleItemsCallback (msg) {
   // Do something with msg...
}

在代理服务器中,我创建了一个控制器,路由到/redis以处理Redis消息:

exports.redisUpdates = function (req, res) {
    // Redis Authentication
    var redisURL = url.parse(process.env.REDISCLOUD_URL);
    var client = redis.createClient(redisURL.port, redisURL.hostname, {ignore_subscribe_messages: false});
    client.auth(redisURL.auth.split(":")[1]);

    // let request last as long as possible
    req.socket.setTimeout(0);

    // Subscribe to channels
    client.subscribe('items', 'users', 'customers');

    // Handle messages
    client.on('message', function (channel, message) {
        res.write('retry: 5000\n');
        res.write('event: ' + channel + '\n');
        res.write('data: ' + message + '\n\n');
        res.flush(); // If I do not add this it doesn't push updates to the client (?)
    });

    //send headers for event-stream connection
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    });
    res.write('\n');

};

在开发环境中本地使用它可以正常工作但在生产中使用它会产生几个不同的错误,应用程序托管在 Heroku 上, Heroku Metrics 显示几个< strong> H18 , H12 H27 错误;

有时/redis来电回复状态为503;

我希望了解的是,如果我正确使用这些服务,为什么所有教程都没有提到res.flush(),我自己发现它让它第一次运行...

1 个答案:

答案 0 :(得分:1)

平心而论,由于一些原因,这个问题并不是真正的问题。我不知道你在谈论哪些教程,因为你没有在问题中引用任何教程。我不能代表编写未引用教程的人发言。他们可能只是错了,或者你想要完成的架构可能会有一些小的不同。我也不知道您在项目中使用的框架或可选中间件。

现在,所有这些都说我可以分享一些可以帮助你的东西。

您发现的大多数教程可能无法打开连接并无限期地从流中读取。当进程结束时,http响应将以.end()或类似的方式关闭。由于HTTP响应是写入流,因此它遵循与任何其他流相同的规则。你可以在这里找到很多关于流的好信息:

https://github.com/substack/stream-handbook

要理解的重要一点是,流可以有一个缓冲区,大多数http框架都能启用压缩,从而导致使用缓冲区。下一个链接中的代码示例是框架在幕后为您做什么的一个很好的例子(当然是最小的实现)

https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/#what-we-ve-got-so-far

由于您希望输出继续更新,您必须等到达到输出缓冲区大小或者必须调用.flush()。

如果您正在使用express,请查看与压缩中间件相关的下一个Stack Overflow帖子。我相信您必须禁用/redis路线。

Node Express Content-Length

我希望这有点帮助。就像我说的那样,很难回答这个问题。 ;)