skynet源码解析--启动篇之三大模块

本文详细解析了skynet的启动过程,包括基本信息初始化如harbor ID、句柄池、消息队列和模块接口,接着重点介绍了优先启动的服务(如日志服务和通用引导服务)、监视器机制、定时器模块的分段计时原理以及网络和工作模块的概述。通过对启动流程的剖析,展示了skynet高效的消息处理和资源管理策略。
摘要由CSDN通过智能技术生成

基本信息初始化

    初始化配置之后,就要开始启动skynet的主要模块。不过,启动模块之前要先初始化一些基本信息。

  • 生成harbor ID。这个ID用一个整型的高八位表示,也就是说master/harbor模式中,同一个集群最多只有256个harbor服务器。
  • 句柄池初始化。这个句柄池主要用来管理服保存务对象的句柄,其中还包括句柄和服务的映射关系,这个句柄具有唯一新(harbor模式下在集群都是唯一的),因此只要知道地址(句柄)你就可以快速找到对应的服务对象。还有skynet采用的是Actor模型,所以这个服务对象其实对应的就是Actor对象。
  • 一级队列初始化。skynet的消息处理采用的是两级消息队列方式,二级消息队列保存在服务对象上,就是说每个服务对象有独立的消息队列。
  • module接口初始化。这个modules类型的全局变量主要保存了加载到skynet中c库的基本信息以及对外提供调用c库的方法。这个可以看作面向对象范畴里面的接口对象,每个加载的c库可以认为是继承了这个接口的类的实例化,所有加载的c库对象都是通过这个接口调用。
  • 定时器模块初始化
  • 网络模块初始化。这里主要是创建一个管道,作为服务对象和网络IO的桥梁从避免IO阻塞对服务器对象的影响。后续讲到服务调度就会知道服务阻塞的危害
    下面是skynet_start文件中的代码,加上了简略的注释:
	//初始化基本信息
	skynet_harbor_init(config->harbor); //生成harbor ID 高八位表示 所以master/harbor模式下同个集群里最多只有256台harbor
	skynet_handle_init(config->harbor); //句柄池初始化,管理服务对象句柄(地址),以及地址和服务的映射关系。
	skynet_mq_init();					//一级消息队列初始化(skynet采用的是两级消息队列模式)
	skynet_module_init(config->module_path); // module接口,这里主要存储加载到skynet中的c库,并对外提供c库方法的接口。这个可以看做是一个接口类,每加载一个c库相当于实例化一个继承该接口的对象。
	skynet_timer_init();				// 定时器模块初始化。
	skynet_socket_init(); 				// 网络模块初始化,这个并非skynet的网络库,这里主要是创建一个管道,作为服务对象和网络IO的桥梁从避免IO阻塞对服务器对象的影响。
	skynet_profile_enable(config->profile); // debug

优先启动的服务

    日志服务:主要负责输出与记录,程序运行中的日志。通用引导服务:用于拉起其他的服务。

	struct skynet_context *ctx = skynet_context_new(config->logservice, config->logger); // 生成日志服务Actor
	bootstrap(ctx, config->bootstrap); //生成通用lua引导服务Actor

监视器

create_thread(&pid[0], thread_monitor, m); //启动监视模块

    监视器的作用监控工作模块(其中的工作线程)对可能出现的死循环通过打印信息发出警告。下面是monitor的数据结构。

struct skynet_monitor {
   
	int version;  // 版本号 -- 其实就是消息的流水号
	int check_version; // 检查版本号
	uint32_t source;  // 源地址
	uint32_t destination; // 目标地址
};

    监视器的工作方式,工作线程每次处理消息之前,version自增,记录源地址(source)和目标地址(destination),然后5秒钟检测一次目标地址是否为空(处理完消息之后置空源地址)且version与check_version相等则提示该工作线程可能死循环(因为该消息已经占用工作线程5秒)。
    thread_monitor中每次检查间隔5秒。

		for (i=0;i<5;i++) {
    // 休息5秒
			CHECK_ABORT
			sleep(1);
		}

    监视器的消息版本号更新与检测。

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) {
   
			skynet_context_endless(sm->destination); //检查目标服务的引用,引用为0则回收,释放工作线程
			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; // 不一致的时候更新
	}
}

定时器模块

create_thread(&pid[1], thread_timer, m);   //启动定时器模块

    skynet的主要模块之一,为服务器提供基础的定时器功能。skynet的定时器是通过计数器的方式实现的,把时间段分成5级,一级为时间近点,即将发生超时的时间段,等待通知处理。后面4级是时间远点,随着时间增长一级一级向前移动直至近点,等待处理。下面是主要的数据结构:

//定时事件
struct timer_event {
   
	uint32_t handle; // 服务地址
	int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值