skynet源码分析(4)--monitor

来源:互联网 发布:苹果手机变音软件 编辑:程序博客网 时间:2024/06/01 07:58

作者:shihuaping0918@163.com,转载请注明作者

skynet对服务的监控做得比较简陋,从设计原则上来说,这样做也是对的,因为框架层能做的,基本就是上报和打日志,上层的业务是变化万千的,不论怎么写,都可能满足不了上层的业务需求。skynet中对服务的监控实现在skynet_monitor.c和skynet_monitor.h中,当服务可能陷入死循环的时候,就打一条日志。具体日志内容详见代码。

#include "skynet_monitor.h"#include "skynet_server.h"#include "skynet.h"#include "atomic.h"#include <stdlib.h>#include <string.h>struct skynet_monitor {    int version; //版本号    int check_version; //上个版本号    uint32_t source; //源    uint32_t destination; //目标};//结构体初始化struct skynet_monitor * skynet_monitor_new() {    struct skynet_monitor * ret = skynet_malloc(sizeof(*ret));    memset(ret, 0, sizeof(*ret));    return ret;}//结构体回收void skynet_monitor_delete(struct skynet_monitor *sm) {    skynet_free(sm);}//触发监控void skynet_monitor_trigger(struct skynet_monitor *sm, uint32_t source, uint32_t destination) {    sm->source = source; //源    sm->destination = destination; //目标    ATOM_INC(&sm->version); //版本号递增}//检查监控,有一个线程专门做这个事情void skynet_monitor_check(struct skynet_monitor *sm) {    if (sm->version == sm->check_version) {//版本号相同        if (sm->destination) { //destination不为0//释放目标服务            skynet_context_endless(sm->destination);//打日志,警告可能有死循环            skynet_error(NULL, "A message from [ :%08x ] to [ :%08x ] maybe in an endless loop (version = %d)", sm->source , sm->destination, sm->version);        }    } else { //版本号不同        sm->check_version = sm->version;    }}

每次消息派发,都会调用skynet_monitor_trigger,一共调两次,第一次参数source和destination是真实的值,也就是不为0。第二次调是在消息派发完成的时候,source和destination都赋0。

如果第一次trigger调用以后,消息派发迟迟不完成,monitor线程第一次检查,会将check_version的值赋为version。然后monitor线程第二次检查,这个时候version和check_version就会相等,而且这时候destination也不为0,就会进入释放目标服务和打印报警的流程。

这一篇只能简单的就事论事, 要真正讲得很清晰,整个脉络贯通需要讲完消息派发才行。