作为服务器中维护系统稳定性和可靠性的一个重要模块,SMS(System
management
service)起着承上启下的作用,它的下面是系统监控服务,直接接受监控模块传递过来的各种监控、状态及警告信息;而它的上面几乎直接面向用户,通过CLI命令、消息或者邮件向用户报告系统部件的警告信息,并给出解决的建议。
可以向SMS输出信息、报告警告状态的模块包括IPMI模块、磁盘模块、PCIE
CE/ME监控模块、电源模块等。不同模块发出的消息格式、内容以及消息存放格式和组织方式都有差异,这就要求SMS对下面提供的接口必须具有良好的兼容性,使得不同的模块都能顺利接入。并且,考虑实际的分工协作的开发过程,以及日益提高的系统复杂性,这就要求SMS必须保证有良好的扩展性,使得新的模块和功能容易加入进来。此外,可能还有更上层的应用需要查询SMS收集到的一些信息。那么,该如何实现所有的这些功能呢?根据笔者的经验,可以从如下的几点考虑:
1、对下面的子模块约定公共的接口函数
为了向上层报告各自模块的状态信息,子模块各自都需要实现一些函数,可以归纳出其中公共的函数,定义成一簇函数操作,从而抽象出公共的接口。每个子模块只需要实现和自己相关的这些函数簇。
2、下面的子模块通过注册的办法告知上层模块
子模块虽然实现了自己的一簇函数,但显然不宜由上层模块直接调用,否则加入、删除一个子模块的时候,都需要加入或者去掉和那个子模块对应的函数。因此,通过注册子模块函数簇组到上层模块的一个函数簇数组当中的办法,不仅仅解决了前面的问题,还一下子使得上下层之间的层次关系一目了然。
3、制定公共的警告统计、归集、存档的策略
下层的多个模块会不停地检测到它底下硬件的状况信息,并把这些信息记录在自己的域中。为此,上层模块只有通过调用底层模块提供给它的接口函数才能收集到各个模块的状态信息或者警告,进而根据指定的策略(比如根据接受到的警告、事件信息的个数是否超过阈值,没被处理的信息是否已经超时)进行上传、归档等操作。
4、对外提供抽象的接口
在实际的工程中,SMS通常作为一个daemon进程在不停地运行,和其下的系统监控模块daemon等互相通信。实际的应用场景中,可能还有上层的应用需要知道系统警告的总数和内容等信息,这就要求SMS除了实现daemon的功能外,还需要实现一些API库函数,以便其他的应用程序使用。
当然,上面的这些只是需要重点考虑的地方,但还不是全部。一个有经验的设计还应考虑到下面的这些问题:
1、为了优化性能,如何设计数据结构,保证上层模块查询ID连续的警告信息时优先从各个模块分配的存储空间而非统一的日志文件中去查询;
2、为了便于调式、加快测试,如何在开始编程时就考虑针对各个模块和系统的测试框架和代码。
3、为了更好地和上层应用交互,SMS本身提供的库需要那些特点才能保证上层应用效率更高。
总而言之,像SMS这种中间层的服务模块的设计和开发,既要从宏观上把握它的位置、功能和应用场景,又要从业务流程和逻辑上深入到它涵盖的各个子模块、相互关系,还要考虑到性能优化、代码可调试和测试驱动开发,这样才能开发出功能正确、性能可靠的系统软件。