本文介绍: (数量可配置),它们不断的从主消息列队中取出一个次级消息队列来,再从次级队列中取去一条消息,调用对应的服务的 callback 函数进行出来。为了调用公平,一次仅处理一条消息,而不是耗净所有消息(虽然那样的局部效率更高,因为减少了查询服务实体的次数,以及主消息队列进出的次数),这样可以保证没有服务会被饿死。③一个服务是用skynet_context作为服务的实例,一个唯一的handle的id作为唯一id识别服务(id即使在集群里面也是唯一)大到小:集群->skynet节点->服务。不为空的次级消息队列。
一、消息队列
①Skynet 维护了一个全局消息队列
,里面放的是诸个不为空的次级消息队列
②在 Skynet 启动时,建立了若干工作线程
(数量可配置),它们不断的从主消息列队中取出一个次级消息队列来,再从次级队列中取去一条消息,调用对应的服务的 callback 函数进行出来。为了调用公平,一次仅处理一条消息,而不是耗净所有消息(虽然那样的局部效率更高,因为减少了查询服务实体的次数,以及主消息队列进出的次数),这样可以保证没有服务会被饿死
③结果:
这样,skynet就实现了把一个消息(数据包)从一个服务发送给另一个服务。
二、集群节点
大到小:集群->skynet节点->服务
①一个集群内可以启动很多个skynet节点,每个节点都会分配到唯一的habor id,每个habor id是8位
②一个节点(即一个进程)内有很多个服务,服务可以狭义地暂且理解为功能模块。
③一个服务是用skynet_context作为服务的实例,一个唯一的handle的id作为唯一id识别服务(id即使在集群里面也是唯一)
④初始化新服务代码
skynet_context_new(const char * name, const char *param) {
// 装载模块
struct skynet_module * mod = skynet_module_query(name);
if (mod == NULL)
return NULL;
void *inst = skynet_module_instance_create(mod);
if (inst == NULL)
return NULL;
// 初始化skynet_context实例
struct skynet_context * ctx = skynet_malloc(sizeof(*ctx));
CHECKCALLING_INIT(ctx)
ctx->mod = mod;
ctx->instance = inst;
ctx->ref = 2;
ctx->cb = NULL;
ctx->cb_ud = NULL;
ctx->session_id = 0;
ctx->logfile = NULL;
ctx->init = false;
ctx->endless = false;
// 初始化服务handle
// Should set to 0 first to avoid skynet_handle_retireall get an uninitialized handle
ctx->handle = 0;
ctx->handle = skynet_handle_register(ctx);//生成服务的handle
// 初始化消息队列
struct message_queue * queue = ctx->queue = skynet_mq_create(ctx->handle);
// init function maybe use ctx->handle, so it must init at last
context_inc();
CHECKCALLING_BEGIN(ctx)
int r = skynet_module_instance_init(mod, inst, ctx, param);
CHECKCALLING_END(ctx)
if (r == 0) {
struct skynet_context * ret = skynet_context_release(ctx);
if (ret) {
ctx->init = true;
}
skynet_globalmq_push(queue);
if (ret) {
skynet_error(ret, "LAUNCH %s %s", name, param ? param : "");
}
return ret;
} else {
skynet_error(ctx, "FAILED launch %s", name);
uint32_t handle = ctx->handle;
skynet_context_release(ctx);
skynet_handle_retire(handle);
struct drop_t d = { handle };
skynet_mq_release(queue, drop_message, &d);
return NULL;
}
}
- 备注:
①服务会向消息队列创建message_queue消息队列
,用来存储发送给该服务的消息的。所有发送给该服务的消息,都要先压到该服务的消息队列中。
②在skynet_handle_register方法中生成一个服务handle,handle是一个32位的整数,在生成handle的时候,是把该节点的harbor id写到了handle的高8
位里面,低24位节点用来分配给本节点的handle,handle唯一标识了一个集群里面的服务
③harbor id只有8位,那么skynet集群最多只能有256个节点
三、消息发送
int skynet_send(
struct skynet_context * context,
uint32_t source, //发送方的handle
uint32_t destination, //接收方的handle
int type, //发送方和接收方处理数据包的协议
int session, //便于协程调用所需的会话,方便resume
void * msg, //消息内容
size_t sz //消息长度
);
typedef int (*skynet_cb)(
struct skynet_context * context,
void *ud,
int type,
int session,
uint32_t source ,
const void* msg,
size_t sz
);
struct skynet_message {
uint32_t source; //消息来源的handle
int session; //会话信息
void * data; //数据
size_t sz; //数据长度
};
四、消息执行
五、服务具体执行的流程
原文地址:https://blog.csdn.net/weixin_43679037/article/details/134807607
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_49276.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。