我有一堆服务(比如C0,C1…… C9),它们应该只在服务S完成初始化并完全运行并准备好用于其他服务后启动。我如何用 systemd 安排它?
在systemd 中使用路径激活和目标对服务S进行排序时,假设服务具有写出某种标志文件的机制。相比之下,这里假设我可以完全控制服务S运行的程序,并且可以在需要时向其中添加 systemd 机制。
如果C服务需要等待S准备就绪,以便它们可以打开到它的套接字连接,那么根本不需要这样做。相反,可以利用服务管理器的早期侦听套接字打开。
包括Laurent Bercot 的 s6、我的 nosh 工具集和 systemd在内的几个系统都有可以尽早打开侦听套接字的方法,这是设置服务的第一件事。它们都涉及服务程序打开侦听套接字之外的其他内容,服务程序在调用时将侦听套接字作为已经打开的文件描述符接收。
具体而言,使用 systemd 可以创建一个套接字单元来定义侦听套接字。systemd 打开套接字单元并进行设置,以便内核网络子系统监听连接;并在产生处理套接字连接的进程时将其作为打开的文件描述符传递给实际服务。(它可以通过两种方式做到这一点,就像inetd可以一样,但对Accept=true与Accept=false服务的细节的讨论超出了本答案的范围。)
重要的一点是,一个人并不一定需要比这更多的顺序。内核在队列中批量处理客户端连接,直到服务程序被初始化,并准备好接受它们并与客户端交谈。
systemd 有一组它可以理解的就绪协议,通过Type=服务单元中的设置逐个指定服务。这里感兴趣的特定准备协议是notify准备协议。有了它,systemd 被告知期待来自服务的消息,当服务准备好时,它会发送一条标记准备好的消息。systemd 会延迟其他服务的激活,直到标记就绪。
使用它涉及两件事:
S,使其调用类似 Pierre-Yves Ritschard 的notify_systemd()函数或 Cameron T Norman 的notify_socket()函数。Type=notify和为服务设置服务单元NotifyAccess=main。 该NotifyAccess=main限制(这是默认值),是因为systemd需要知道忽略来自恶作剧(或只是简单的故障)计划的消息,因为系统上的任何进程都可以发送邮件到systemd的通知插座。
可以优先使用 Pierre-Yves Ritschard 或 Cameron T Norman 的代码,因为它不排除在 UbuntuBSD、Debian FreeBSD、实际 FreeBSD、TrueOS、OpenBSD 等上使用这种机制的可能性;systemd 作者提供的代码确实排除了这些。
要避免的一个陷阱是systemd-notify程序。它有几个主要问题,其中最重要的是,使用它发送的消息最终可能会被 systemd 丢弃而未经处理。在这种情况下,最大的问题是它不作为服务的“主要”进程运行,因此必须向S系统上的每个进程打开服务的就绪通知NotifyAccess=all。
另一个要避免的陷阱是认为forking协议更简单。它不是。正确地执行此操作涉及直到(一方面)程序的所有工作线程都在运行之前不分叉和退出父级。这与分叉的绝大多数守护进程实际上分叉的方式不符。
sd_notify(). systemd 手册页。Freedesktop.org。systemd-notify. systemd 手册页。Freedesktop.org。| 归档时间: |
|
| 查看次数: |
6275 次 |
| 最近记录: |