searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

agent维活的几种方法

2023-05-15 12:27:32
17
0

agent是一种计算机程序,它的特点包括持久运行、无需人工干预自主执行某些活动、能够与其他组件协调共同完成任务、能够感知并响应环境变化等特点。

在实际运行中,由于计算机资源、人为误操作等原因,agent往往很难实现长时间持久化的运行。

笔者整理了几种agent维活方法:

supervisord

首先的想法是使用其他进程来监听agent进程,当agent进程停止后主动拉起。这种方式的典型工具是supervisord。

Supervisord是一个用Python语言编写的进程管理工具,它可以很方便地监听、启动、停止、重启一个或多个进程。当一个进程意外被杀死,Supervisor监听到进程死后,可以很方便地让进程自动恢复,不再需要程序员或系统管理员自己编写代码来控制。

supervisord提供了supervisorctl命令来管理它所管理的任务,例如,可以使用supervisorctl status命令来查看所有进程的状态,或者使用supervisorctl start myprogram命令来启动名为myprogram的进程,stop命令可以停止一个进程,restart命令可以重启一个进程。

详细命令可以参考官方文档:http://supervisord.org/

 

Supervisord本身是一个常驻进程,在大多数情况下都能够稳定运行,但是如果它意外崩溃或被杀死,就需要有其他机制来重启supervisor进程。比如我们再使用一个supervisor2进程来监听并维活supervisor进程。 比如定时任务corntab:

corntab

Crontab是Linux系统中用于定时执行任务的命令。它可以让用户在指定的时间自动执行某些命令或脚本。Crontab命令的格式为:

* * * * * command

其中,星号代表时间的各个字段,分别表示分钟、小时、日期、月份和星期几。例如*表示任意时间,*/5表示每5分钟,1,2,3表示第1、2、3分钟等。

可以使用crontab -e命令来编辑当前用户的Crontab文件,并添加定时任务。也可以使用crontab -l命令来查看当前用户的Crontab文件。

使用Crontab添加脚本定期检查Supervisord进程是否在运行,如果不存在则启动它。下面是一个简单的示例脚本,它检查Supervisord进程是否在运行并自动拉起:

#!/bin/bash

# 检查 supervisord 是否正在运行
pid_cnts=$(ps -ef | grep supervisord | wc -l)

# 如果 supervisord 未运行,则启动它
if [ $pid_cnts -eq 0 ]; then
    echo "my_program is not running, starting it"
    /usr/bin/supervisord  &
fi

将上面的脚本保存为一个文件,例如/usr/local/bin/check_supervisord.sh,并使用chmod +x /usr/local/bin/check_supervisord.sh命令添加执行权限。

然后使用crontab -e命令编辑当前用户的Crontab文件,并添加一行,每5分钟运行一次check_supervisord.sh脚本:

*/5 * * * * /usr/local/bin/check_supervisord.sh

在实际使用过程中,我们还需要考虑脚本执行超时、执行失败、crontab重复拉起导致脚本并发执行等等问题,实际生产可用的脚本要比上述脚本复杂得多。

另外,脚本只会在crontab表达式所描述的时间点执行,这个时间间隔就是程序自动拉起的最大间隔时间,在实际工作中crontab脚本一般设置为分钟级,分钟级的间隔对于某些应用来说可能还是太长了。

 

那么有没有一种机制,能够在supervisor异常退出后能够直接感知到,并自动拉起呢?有的,比如我们接下来要说的systemd机制:

systemd

你可以使用操作系统提供的进程监控工具来监控Supervisord进程并在需要时重启它。

在Linux系统上,可以使用systemd来管理Supervisord进程。可以创建一个systemd服务来启动Supervisord,并配置服务在Supervisord崩溃时自动拉起。

在/etc/systemd/system/目录下创建一个名为supervisord.service的文件,然后在其中添加如下内容:

[Unit]
Description=Supervisor process control system for UNIX
Documentation=http://supervisord.org
After=network.target

[Service]
ExecStart=/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target


上面的配置指定了Supervisord的启动命令、停止命令和重载命令。它还指定了当Supervisord崩溃时,systemd应该在5秒后重启它。

创建完成后,你可以使用systemctl start supervisord命令来启动Supervisord服务,或者使用systemctl enable supervisord命令来配置Supervisord服务在系统启动时自动启动。

关于systemd的更多说明和用法可以参考https://systemd.io/

 

systemd会感知到进程的异常退出(返回值不为0),并自动拉起。但是实际环境中,某些应用程序可能会陷入某种异常状态,进程仍然存活,但是无法正常工作了。systemd提供了watchDog机制来自动重启进程

要使用 Watchdog 来监测系统运行情况,需要以下2个步骤:

1、在 service unit 文件中添加配置:在 [Service] 部分中添加 WatchdogSec 配置来指定 Watchdog 的超时时间。

2、在程序中使用 sd_notify 函数来向 systemd 发送心跳信号,以通知 systemd 程序仍在运行。

下面的例子中配置了一个名为 my_program 的程序,并启用了 Watchdog 功能:添加了 WatchdogSec=30s 配置来指定 Watchdog 的超时时间为 30 秒。这意味着如果 my_program 在 30 秒内未向 systemd 发送心跳信号,则 systemd 将认为该程序已经挂起,并根据配置的重启策略(例如 Restart=on-failure)来重启该程序。

[Unit] 
Description=My Program 

[Service] 
ExecStart=/path/to/my_program 
Restart=on-failure 
WatchdogSec=30s

[Install] 
WantedBy=multi-user.target

在程序中发送心跳信号的代码如下:

import (
	"github.com/mdlayher/sdnotify"
	"log"
	"time"
)

func StartWatchDogNotify() {
	n, err := sdnotify.New()
	if err != nil {
		log.printf("error create systemd notify: err=%+v", err)
		return
	}

	// 创建之后马上发一条
	err = n.Notify(sdnotify.Ready)
	if err != nil {
		log.printf("error send sdnotify.Ready notify: err=%+v", err)
		return
	}

	go func() {

		ti := time.NewTicker(time.Second * 10)
		defer ti.Stop()

		for true {
			select {
			case <-ti.C:
				log.printf("send watchdog notify")
				err := n.Notify("WATCHDOG=1")
				if err != nil {
					log.printf("error send WATCHDOG notify: err=%+v", err)
					return
				}
			}
		}
	}()
}

 

总结

本文中讨论了几种进程维活的机制,实际生产环境各不相同,需要因地制宜选择或者综合使用,以达到更好的维活效果。

0条评论
0 / 1000
唐****程
14文章数
1粉丝数
唐****程
14 文章 | 1 粉丝
原创

agent维活的几种方法

2023-05-15 12:27:32
17
0

agent是一种计算机程序,它的特点包括持久运行、无需人工干预自主执行某些活动、能够与其他组件协调共同完成任务、能够感知并响应环境变化等特点。

在实际运行中,由于计算机资源、人为误操作等原因,agent往往很难实现长时间持久化的运行。

笔者整理了几种agent维活方法:

supervisord

首先的想法是使用其他进程来监听agent进程,当agent进程停止后主动拉起。这种方式的典型工具是supervisord。

Supervisord是一个用Python语言编写的进程管理工具,它可以很方便地监听、启动、停止、重启一个或多个进程。当一个进程意外被杀死,Supervisor监听到进程死后,可以很方便地让进程自动恢复,不再需要程序员或系统管理员自己编写代码来控制。

supervisord提供了supervisorctl命令来管理它所管理的任务,例如,可以使用supervisorctl status命令来查看所有进程的状态,或者使用supervisorctl start myprogram命令来启动名为myprogram的进程,stop命令可以停止一个进程,restart命令可以重启一个进程。

详细命令可以参考官方文档:http://supervisord.org/

 

Supervisord本身是一个常驻进程,在大多数情况下都能够稳定运行,但是如果它意外崩溃或被杀死,就需要有其他机制来重启supervisor进程。比如我们再使用一个supervisor2进程来监听并维活supervisor进程。 比如定时任务corntab:

corntab

Crontab是Linux系统中用于定时执行任务的命令。它可以让用户在指定的时间自动执行某些命令或脚本。Crontab命令的格式为:

* * * * * command

其中,星号代表时间的各个字段,分别表示分钟、小时、日期、月份和星期几。例如*表示任意时间,*/5表示每5分钟,1,2,3表示第1、2、3分钟等。

可以使用crontab -e命令来编辑当前用户的Crontab文件,并添加定时任务。也可以使用crontab -l命令来查看当前用户的Crontab文件。

使用Crontab添加脚本定期检查Supervisord进程是否在运行,如果不存在则启动它。下面是一个简单的示例脚本,它检查Supervisord进程是否在运行并自动拉起:

#!/bin/bash

# 检查 supervisord 是否正在运行
pid_cnts=$(ps -ef | grep supervisord | wc -l)

# 如果 supervisord 未运行,则启动它
if [ $pid_cnts -eq 0 ]; then
    echo "my_program is not running, starting it"
    /usr/bin/supervisord  &
fi

将上面的脚本保存为一个文件,例如/usr/local/bin/check_supervisord.sh,并使用chmod +x /usr/local/bin/check_supervisord.sh命令添加执行权限。

然后使用crontab -e命令编辑当前用户的Crontab文件,并添加一行,每5分钟运行一次check_supervisord.sh脚本:

*/5 * * * * /usr/local/bin/check_supervisord.sh

在实际使用过程中,我们还需要考虑脚本执行超时、执行失败、crontab重复拉起导致脚本并发执行等等问题,实际生产可用的脚本要比上述脚本复杂得多。

另外,脚本只会在crontab表达式所描述的时间点执行,这个时间间隔就是程序自动拉起的最大间隔时间,在实际工作中crontab脚本一般设置为分钟级,分钟级的间隔对于某些应用来说可能还是太长了。

 

那么有没有一种机制,能够在supervisor异常退出后能够直接感知到,并自动拉起呢?有的,比如我们接下来要说的systemd机制:

systemd

你可以使用操作系统提供的进程监控工具来监控Supervisord进程并在需要时重启它。

在Linux系统上,可以使用systemd来管理Supervisord进程。可以创建一个systemd服务来启动Supervisord,并配置服务在Supervisord崩溃时自动拉起。

在/etc/systemd/system/目录下创建一个名为supervisord.service的文件,然后在其中添加如下内容:

[Unit]
Description=Supervisor process control system for UNIX
Documentation=http://supervisord.org
After=network.target

[Service]
ExecStart=/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target


上面的配置指定了Supervisord的启动命令、停止命令和重载命令。它还指定了当Supervisord崩溃时,systemd应该在5秒后重启它。

创建完成后,你可以使用systemctl start supervisord命令来启动Supervisord服务,或者使用systemctl enable supervisord命令来配置Supervisord服务在系统启动时自动启动。

关于systemd的更多说明和用法可以参考https://systemd.io/

 

systemd会感知到进程的异常退出(返回值不为0),并自动拉起。但是实际环境中,某些应用程序可能会陷入某种异常状态,进程仍然存活,但是无法正常工作了。systemd提供了watchDog机制来自动重启进程

要使用 Watchdog 来监测系统运行情况,需要以下2个步骤:

1、在 service unit 文件中添加配置:在 [Service] 部分中添加 WatchdogSec 配置来指定 Watchdog 的超时时间。

2、在程序中使用 sd_notify 函数来向 systemd 发送心跳信号,以通知 systemd 程序仍在运行。

下面的例子中配置了一个名为 my_program 的程序,并启用了 Watchdog 功能:添加了 WatchdogSec=30s 配置来指定 Watchdog 的超时时间为 30 秒。这意味着如果 my_program 在 30 秒内未向 systemd 发送心跳信号,则 systemd 将认为该程序已经挂起,并根据配置的重启策略(例如 Restart=on-failure)来重启该程序。

[Unit] 
Description=My Program 

[Service] 
ExecStart=/path/to/my_program 
Restart=on-failure 
WatchdogSec=30s

[Install] 
WantedBy=multi-user.target

在程序中发送心跳信号的代码如下:

import (
	"github.com/mdlayher/sdnotify"
	"log"
	"time"
)

func StartWatchDogNotify() {
	n, err := sdnotify.New()
	if err != nil {
		log.printf("error create systemd notify: err=%+v", err)
		return
	}

	// 创建之后马上发一条
	err = n.Notify(sdnotify.Ready)
	if err != nil {
		log.printf("error send sdnotify.Ready notify: err=%+v", err)
		return
	}

	go func() {

		ti := time.NewTicker(time.Second * 10)
		defer ti.Stop()

		for true {
			select {
			case <-ti.C:
				log.printf("send watchdog notify")
				err := n.Notify("WATCHDOG=1")
				if err != nil {
					log.printf("error send WATCHDOG notify: err=%+v", err)
					return
				}
			}
		}
	}()
}

 

总结

本文中讨论了几种进程维活的机制,实际生产环境各不相同,需要因地制宜选择或者综合使用,以达到更好的维活效果。

文章来自个人专栏
agent
14 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0