这……第一次见到这种设计 LOL
不要这样搞。缺陷太多了:
其实这类工作业界早有成熟的模型,压根不需要多线程,也不需要搞什么复杂的增加/删除源的逻辑。
要点:
具体来说,你可以写两个程序。第一个程序可以叫scheduler,第二个叫worker。
scheduler由crontab或计划任务每分钟启动;它要在某个文件里记住自己已经被调用了多少次(可以通过系统时钟双重确认,但并不必要);每分钟/十分/十五分/半小时/一小时(同样做到配置文件里)调用worker。
比如,scheduler.ini里面有一项是:
[schedule_008]
interval=30 #每30分钟调用
worker=/path/to/worker #检查执行者所在路径
argument=/path/to/half_hourly #告警源配置文件所在路径
注意我用了Linux路径风格。Windows下把“/”改成“”就行了。
scheduler读取scheduler.ini,发现schedule_008的interval是30,意思就是每三十分钟执行worker指定的命令;执行这个命令时,要给它传递一个命令行参数,也就是下面的argument。
worker被执行时,从自己得到的命令行参数指定目录读取所有配置文件。这些配置文件里面就是告警源信息。
比如:
ip=192.168.0.123
port=3339
user=user
passwd=123456
换句话说,worker完全可以不知道自己的被调用频率;它只是在被唤醒时连接到192.168.0.123的3339端口,然后以user用户登录(密码123456)、检查有无告警、若有告警执行既定流程罢了。
你看,这个设计把各种功能全部解耦,平常不占用资源,每分钟周期性检查、执行时才载入告警源配置信息。
你完全可以随时随地添加一个worker(比如加个每7分钟检查的worker)、随时随地更换worker(比如有告警就发短信的worker、有告警就发邮件的worker、有告警就拉防空警报的worker,等等。没错,你甚至可以添加告警级别支持,把普通、严重、危急等告警分开:很简单,在硬盘上建立一个新的目录,然后配置一个不同的worker即可)。
同样的,你也可以随时随地导入一百万个告警源,或者一条rm命令删除所有告警源,os本身就可以保证这个操作的安全性——反正你的worker就是读取配置文件、然后遍历里面列出的每一个告警源而已(当然,如果有必要,你也可以在worker里面并行,从而提高处理速率。比如你需要处理一百万或者更多告警源时,可能就有必要这么做了)。
总之,这个设计是极其灵活却又极度简洁的。最简单的worker甚至可以只是一个脚本,读取配置后用wget取得信息然后grep再执行个alarm命令即可。
这个方案好写、好测,效率极高,又允许你随意扩展——比如增加一个ram加速插件,监控硬盘,把所有配置文件处理后同步到RAMDisk;然后修改scheduler.ini里面的路径信息,从而让worker到RAMDisk读取配置信息;再比如添加一个图形化的管理工具,自动展示/添加/删除/修改甚至临时禁用/使能某个被监控的源;还有前面提到的,通过目录分划给不同告警的检查频率、严重程度分类,等等——可以支持几乎无限的需求。
只要业务水平不太差,这个方案一旦写好便一劳永逸,以后随便要什么需求也不过是多写一个独立的简单小程序的事。它完美实现了“对扩展开放”和“对修改封闭”这两个设计目标,彻底免除了码农们加班改bug、996/007但是工作还是完不成之苦……
因此,这个思路在很多地方得到了应用——比如Linux的crontab配置就是这样做的,它的init level、Debian系的source list等等等等,也都是这个思路。
少即是多,这就是Linux哲学。功能越专一、方案越简洁,反而越灵活、越方便扩展,越能支持千变万化的需求、甚至作为基础设施,扩展成一个庞大而复杂的项目——注意复杂是简无可简,并不是自寻烦恼。
把一个项目搞的很麻烦、没有一个人知道全貌、甚至几乎没人能读懂、这很容易,水平越低越容易做到;但想要把一个项目做简单、然后用简单到明显没有错误的代码完成多变复杂的需求,这反而需要极深的功底。