部署生产环境的Node.js服务器

75

我写了一个Node.js应用程序,想要在我们的生产机器上运行它。这似乎是一个相当普遍的需求,但我找不到一个合适的解决方案。难道没有为部署生产Node.js应用程序建立的解决方案吗?

这个应用程序很简单(<100 LOC),但需要非常高效、可靠,并且可以连续运行数年而不需要重新启动。它将在一个大型站点上运行,每秒钟有数十个连接(该应用程序不用作Web服务器,只有JSON API)。

以下是我考虑过的方法,但我仍然不确定:

使用框架(例如Express)

由于应用程序需要高性能且非常简单,因此我要避免以框架形式添加膨胀。

使用nohup启动服务器

主要问题在于异常处理,我们(显然)不希望整个服务器因异常而崩溃。据我所知,将整个应用程序包装在try {} catch {}循环中无法解决问题,因为Javascript解释器在异常发生后处于不可预测的状态。这正确吗?

使用类似Forever的东西

我在我们的FreeBSD机器上安装了Forever,但它非常不稳定。它最终产生了无法从Forever中终止的无尽进程。我不太自信用Forever运行生产应用程序。似乎Upstart(类似的工具,但更通用)也无法在FreeBSD上运行。

托管解决方案(例如Heroku、Rackspace、Amazon EC2等)

这可能是最简单的解决方案,但我们已经有了其他Web服务器的严重硬件。出于财务考虑,这是不明智的。

肯定有一些已建立解决方案可以解决这个问题吧?我有什么遗漏了吗?


Upstart是FreeBSD上sysvinit的替代品。 - chovy
3
对于阅读此SO的2014年人群,“Forever”不应因为在两年前的一个案例中失败而被忽视。我最近几个月使用它取得了成功。请注意,本句中的"Forever"代表一种软件工具或框架,上下文未提供更多信息。 - Eat at Joes
7
对于阅读此SO的2015年用户,请使用PM2代替Forever。请注意不要改变原文意思,尽可能使翻译通俗易懂。 - Nikola
6个回答

41
  • 你真的应该使用框架(我推荐像Express这样经过实战测试的框架),除非你想自己处理会话、Cookie、中间件等。Express非常轻巧。
  • 不要用nohup启动服务器:你应该用正常的“node”命令来启动它。而且,Express会在路由中包装try-catch语句,所以如果路由出现问题,你的服务器也不会崩溃。但是,如果你的服务器确实出现了严重问题,你不必担心重启它(此外,如果你至少有2-3个进程,只有一个进程会死亡,所以至少剩下1-2个进程,用户不会感到任何影响)。
  • 对于监控,我个人更喜欢一些操作系统级别的工具,比如UpstartMonit
  • 托管解决方案:既然你已经有了自己的硬件设备,就不需要再投资其他东西了。只需使用一种负载均衡器(可能是nginx或node-http-proxy)来代理即可。

15

请参见托管Node.js应用程序

该教程将指导您设置一个服务器,可以为服务器端JavaScript应用程序托管Node.js应用程序。目前,Node.js托管选项归结为运行与Web服务器通信的Node守护进程。大多数Web服务器可以代理到不同的端口,因此您可以使用Apache或nginx来实现此目的。


2
链接已损坏。 - Jorge Gil

6

5
这里有三个问题,我想。
问题0:“我的node应用程序是否应该使用框架?”
问题1:“如何在生产机器上运行node服务器?”
问题2:“如何将node应用程序部署到生产环境?”
对于问题1,我真的很喜欢Cluster(尽管最新的Node版本内置了类似的功能,所以你可能要试试)。我曾经成功地使用过像Monit/Upstart这样的工具来监视操作系统级别的事件,并确保你的服务器处于良好状态。(这是监视Ruby Thin服务器的N个集群,但是同样的道理)。
根据流量大小,您可能需要在多台机器上运行cluster,然后在其前面放置负载均衡器。这取决于您的流量、请求完成所需的时间/阻塞事件循环的时间以及每台机器启动的处理器/节点实例数量。
框架提供更好的错误处理,并捕获会导致正常node.js应用程序退出的错误。如果没有框架,确保您在node.js中阅读错误处理方面的资料。 问题2: 我认为Node社区尚未有良好的部署标准。你可以尝试使用Ruby的Capistrano工具(这里是一个讨论使用Capistrano部署集群的博客链接)。
Capistrano的不好之处是它会做出一些可能不正确的假设(例如:你正在部署一个Rails项目),因此你可能会经常与框架进行斗争。
我的通用部署解决方案是Python的Fabric工具,它提供了部署工具,让你做你需要做的事情。
另一个部署选项是“云端”,例如Nodester:让他们来处理它。

2

您可能会在ServerFault上获得更好的答案,但是这里有一个用户的经验描述, 使用supervisord。您需要使用某种进程监视器来保持node进程活动,并且另一个常见的建议似乎是以某种方式反向代理到node进程。我可能会选择nginx(这样您可以让nginx处理日志记录、身份验证或任何其他高级HTTP功能,而不是将它们某种方式编入节点),但前面提到的文章在评论中也提到了haproxy,这可能更轻量级。您选择的反向代理可能主要取决于您是否需要WebSocket支持。

我不确定是否存在更多“标准”的工作流程适用于node;它还没有像Rails那样成熟,后者有无数种方法来保持Web应用程序运行。


0
Cloudkick的工程师们写了一个很好的解决方案。它被称为Cast, http://cast-project.org/
在您的服务器和工作站上安装Cast。您可以在服务器上启动cast-agent并使用服务器的cast实例进行签名,然后创建“bundles”,将它们上传到服务器,并从它们中创建/升级/销毁以及启动/停止您的实例。当服务崩溃时,Cast将自动重新启动您的服务。您还可以远程跟踪stdout/strerr,并获取正在运行的实例和PID#列表,并从工作站管理您的实例/服务器(无需SSH)。文档略有过时,但是结果值得稍微多做一点工作。所有交互/命令都通过HTTPS和RESTful API完成。
在此之前,我使用SCP/SSH手动执行所有升级操作。我们使用supervise来保持所有内容的正常运行。我们再也没有回头看过。

1
它挂了,Jim!网站现在充满了SEO垃圾,Google对“node.js cast”没有发现任何有趣的内容。 - Sergey
是的,它已经被放弃了。我们目前正在维护一种内部版本。该存储库可以在以下位置找到:https://github.com/cloudkick/cast - Ryan Olds

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