【问题标题】:Understanding how to use Redis with Node.js and Server Sent Events了解如何将 Redis 与 Node.js 和服务器发送事件一起使用
【发布时间】:2017-01-26 21:14:38
【问题描述】:

我的项目是使用 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 显示几个 H18、H12H27 错误;

有时/redis调用返回状态503

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

【问题讨论】:

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


    【解决方案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

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

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 1970-01-01
      相关资源
      最近更新 更多