我正在使用 Sinatra 设计一个 Web 服务,我需要在服务启动时执行某些操作,而在服务器停止时执行一些其他操作。
如何注册这些操作以与 sinatra 完全集成?
谢谢。
答案取决于您需要如何执行操作。它们是否需要为每个 ruby 进程运行,还是只需要为服务运行一次。我想这是所有服务的一次,并且在最新的情况下:
您可能想在 Sinatra 应用程序启动之前运行一些代码,但这并不是您所期望的行为。稍后我会解释为什么。解决方法是在您的 sinatra 类之前添加代码,例如
require "sinatra"
puts "Starting"
get "/" do
...
end
顺便说一句,您也可以在 config.ru 中添加一些代码,效果相同,但我不知道哪个更丑。
为什么这是错误的?因为当您托管您的 Web 服务时,将触发许多 Web 服务器实例,并且每个实例都将执行 puts 方法或您的“启动”代码。当您想要初始化应用程序实例本地的东西时,这是正确的,例如数据库连接,但不初始化所有它们共享的东西。
关于代码最后触发的问题,你不能(或者你可以用一些非常丑陋的解决方法,但你会以与开始时相同的问题结束)。
因此,处理开启和关闭操作的最佳方式是将其包装在您的任务中,以触发您的服务。
并阻止它
您可以通过直接从 ruby 启动您的应用服务器,将它们包装到一个单一的 rake 任务中,就像我在https://github.com/TactilizeTeam/photograph/blob/master/bin/photograph中所做的那样。
这样,您可以在启动服务之前轻松添加一些代码以运行,仍然将其保留在单个任务中。通过一些管道,我想您可以启动多个精简实例,然后允许您启动您的精简(或任何您使用的)实例集群,并且仍然有一项任务可以依赖。
我想说向 SIGINT 信号添加处理程序可以让您在退出之前运行一些代码。请参阅http://www.ruby-doc.org/core-1.9.3/Signal.html了解如何执行此操作。您可能想检查 Thin 是否还没有为该信号注册陷阱,我不确定这是在库中处理还是在用于启动 Thin 的脚本中处理( $PATH 中的“瘦”可执行文件)。
处理退出的另一种方法是拥有一个看门狗进程,该进程检查您的集群是否正在运行,如果没有更多实例在运行,则可以确保正在运行停止代码。