1

我有一些服务器和其他守护程序需要以正确的顺序启动。

我已经从骨架脚本创建了 init.d 脚本,并且可以安装它们以使用编号命名系统以正确的顺序启动,但仍然存在一些问题:

一个服务器('serverA')需要初始化一个数据库连接,然后监听一个套接字。然后另一个服务器('serverB')需要连接到该套接字,如果前面的进程尚未侦听,则连接将失败。有没有办法阻止 serverA 的 init.d 脚本终止,直到 serverA 开始侦听?在 serverA init 终止之前,serverB init 不会启动。

现在,设置的工作原理是让 serverB 重试连接直到它成功,但这种方法似乎很脆弱。我想对如何强制排序有更确定的理解。

4

3 回答 3

3

我不认为它是脆弱的——至少我能想到它不会脆弱的场景。重试时间为 5 秒,一点也不差。它是一种 KISS 方法,没有任何您不理解的极端情况。

使分布式环境同步并不适合胆小的人,并且在您的示例中它过大了。

为了让你对你的方法有信心,我可以告诉你,我有几十个手写的复杂服务器进程分布在一个网络农场上,即使数据库服务器消失了,或者网络中继线消失了,它们也从未让我感到悲伤down 等。它们只是继续以降级模式运行,直到数据库恢复。

于 2009-12-05T17:04:26.603 回答
3

如果服务器侦听域套接字,您可以构建一个轮询套接字的循环。在 bash 中可能有一种更简单的方法来执行此操作,但它可能类似于:

for i in 1 2 3 4 5; do
  if [ -e '/var/run/myserver.sock' ]; then
    break
  fi
done

另一种解决方案是让您的服务器在打开侦听套接字之前不进行守护进程。这样,init 脚本将暂停,直到进程守护进程,这保证了套接字可用。

当然,这取决于您的应用程序自己执行守护进程,而不是通过其他方式。(“/usr/bin/myserver &” 等。)

更新:

另请注意,您现在所做的都是 System-V 样式的 init。Ubuntu 实际上使用的是 Upstart,它是一个基于事件的系统,而不是一系列脚本。您可以选择使用 upstart 作业而不是 System-V 初始化脚本,并从您的服务器触发自定义 Upstart 事件,这将触发您的第二个服务器的启动。

入门指南的最底部有一个示例。我不知道是否有 API 方式,但这可能只是“system("/bin/initctl emit myevent");”的问题 在您的第一台服务器中的正确时间点。具有更多Upstart经验的其他人可能能够更好/更深入地阐述。

于 2009-12-05T17:45:33.307 回答
3

是的,这是我要回答的问题,但我发现这种技术很有用,并且正在与其他遇到类似问题的人分享。

我发现 socat 在等待套接字或端口时非常有用。一个 init.d 脚本,如:

case “$1″ in
  start)
  echo '--benign phrase' | socat - UNIX-CONNECT:/path/to/socket,retry=10,intervall=1
;;

将等到套接字变为可写,然后返回。不涉及守护进程,因此它会阻止更高编号的 init.d 脚本的执行,直到它完成。

使用这样的服务员脚本会减慢启动顺序,因此不是最佳的,但与在脚本中散布“sleep n”语句的非常脆弱的方法相比,这是一个很大的改进。

于 2010-02-22T20:32:59.870 回答