了解如何通过Node.js和Server Sent Events使用Redis

我的项目使用Nodejs作为代理服务器与外部API进行通信。

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

这是我第一次使用Redis和SSE,在网上寻找教程似乎很容易实现,我做到了。

在客户端,我刚刚创build了一个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... } 

在代理服务器中,我创build了一个路由到/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'); }; 

在开发环境中本地使用它可以正常工作,但在Production中使用它会产生几个不同的错误,应用程序在Heroku上托pipe, Heroku Metrics显示多个H18H12H27错误;

有时候/redis调用返回状态503 ;

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

平心而论,由于几个原因,这个问题不是真的可以解决的。 我不知道你在说什么教程,因为你没有提到任何问题。 我不能代表那些编写未经引用的教程的人发言。 他们可能只是错了,或者你尝试完成的架构在一些小的方面有所不同。 我也不知道你在项目中使用了什么框架或可选的中间件。

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

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

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

重要的是要理解的是,一个stream可以有一个缓冲区和大多数HTTP框架启用压缩,导致使用缓冲区。 下一个链接中的代码示例就是一个很好的例子,说明一个框架在幕后会为你做些什么(当然是最小的实现)

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

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

如果您使用快递,请查看与压缩中间件相关的下一个堆栈溢出文章。 我相信你必须禁用你的/redis路由。

节点Express内容长度

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