实时更新Node.js服务器

我想devise一个实时更新的Node.js Express服务器,可能有一个特定的路线,比如/ update,它会加载一个新的configuration文件。 我现在唯一担心的是当更新发生时服务器可能处于任何状态。 如果在用户请求处理JS消息时加载新的configuration文件,则在用户请求的开始处可能有一个configuration,在请求完成之前,可能会在加载新的configuration文件时进行第二个configuration。 我能想到的唯一方法是阻止服务器停留至less一分钟(保持服务器正常运行,但完全阻止任何传入的请求),然后更新服务器并将其重新联机,但这并不是真的热重载或实时更新的最佳forms是?

我怎么能以某种方式欺骗JS事件循环,以便一旦所有请求都完成,configuration文件只会被加载,并延迟任何新的请求,直到configuration加载后?

一种algorithm是:

  1. 设置一个标志“开始重新configuration”
  2. 上面的标志防止任何新的请求被处理(使用Express中间件)
  3. 检查所有当前的请求是否完成(在这里不能想到比轮询循环更好的东西)
  4. 一旦检查完成,加载新的configuration
  5. 一旦configuration被加载,切换标志从(1)

免责声明:我没有尝试过这种生产。 其实我根本没有尝试过。 而我相信这个想法是理智的,沿途可能会有隐藏的陷阱,目前我不知道。

有许多Node.js开发人员往往忘记/不完全意识到:

一次只能执行一个JavaScript语句。

不要紧,你可以做asynchronousI / O或稍后执行一个函数。 不pipe你怎么努力,你写的所有JS代码都是在一个线程中执行的,没有并行性。 只有底层的实现(完全不在我们的控制之下)可以并行地执行。

这对我们有帮助,因为只要我们的更新过程是同步的,就不会执行其他JS代码(即客户端响应)。

configuration实时修补

防止configuration变化的解决scheme很简单:

每个请求都有自己的应用程序configuration副本。

如果您的应用程序的configuration驻留在JavaScript对象中,则只需为每个新请求克隆该对象即可。 这意味着即使您突然更改configuration,也只会应用于新的传入请求。

有很多克隆(甚至是深度克隆)对象的模块,但是因为我相信我是最好的,所以我会利用这个机会进行一些小的自我推销 – 语义合并 。

代码实时修补

这有点棘手,但应该有足够的努力一般可能。

这里的技巧是首先删除/取消注册当前的Express路由 ,清除Node requirecaching ,再次require更新的文件并重新注册路由处理程序。 现在,Express将使用旧代码完成所有待处理的请求(这是因为只要代码包含活动对象引用 – 它要求reqres ),Node就不能从内存中删除这些旧函数,并使用新的必需模块/路由新的传入请求。 一旦没有更多的旧代码开始请求,旧代码应该从内存中释放。

请求处理期间,您不能在任何地方使用require否则您将面临与更改configuration中请求相同的问题。 您当然可以在模块级范围使用require ,因为在需要模块本身时会执行require ,因此是同步的。

例:

 // app/routes/users.js (or something) // This is okay, because it is executed only once - when users.js // itself is required var path = require('path') // This function is something you would put into app.use() module.exports = function usersRoute (req, res, next) { // Do not use require() here! It will be executed per-request! } 

我认为,而不是循环请求到服务器,你可以使用WebSocket。

这样,当你提到的configuration文件发生变化时,服务器可以向用户发送消息,以便刷新数据。

如果您使用nodeJS和Express,这将帮助您:

与NodeJS的Socket.io

服务器将等待某个用户或任何人的信号,并将信号发送给所有用户,以便他们获得新的数据

Node.js的:

 var express = require('express'); var app = express(); var server = require('http').createServer(app); var io = require('socket')(server); var port = process.env.PORT || 3000; server.listen(port, function () { console.log('Server listening at port %d', port); }); app.use(express.static("/PATH_TO_PROJECT")); io.on('connection', function (socket) { socket.on('someone update data', function (data) { socket.to(socket.room).broadcast.emit('data updated', {params:"x"}); } }); 

同时,如果有任何改变,客户将会听取:

View.js:

 var socket = io(); socket.on('new message', function (data) { liveUpdate(data); }); 

我希望我能正确理解你问的问题

这是一个很好的解决问题。

一个可能的解决scheme可能是:你从父控制器的每个path派生的控制器。 父控制器可以在请求到达时将一个属性ON(一个标志/文件)标记出来,并且在回送该响应时将其closures。

现在为每个面向前端的快速端点子控制这个父控制器。 如果现在请求“/ update”,那么更新控制器将通过FLAG知道服务器是否繁忙,如果更新成功或不成功,则发回应答。

对于更新失败,前端可能会回退到“/ update”端点,并带有一些退避计划。

这个scheme可能适合你…