当前位置: 首页 > article >正文

skynet学习笔记(12/05未完待续)

文章目录

    • 一、消息队列
    • 二、集群节点
    • 三、消息发送
    • 四、消息执行
    • 五、服务具体执行的流程

一、消息队列

①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个节点

三、消息发送

  • 简介
    这里简单讲解如何从一个服务发送给另一个服务的
  • 函数
    这里涉及到的函数是skynet_send 和 callback
  • 函数定义
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;      //数据长度
};

四、消息执行

五、服务具体执行的流程


http://www.kler.cn/a/159195.html

相关文章:

  • 控制器ThinkPHP6
  • VSCode设置
  • Spring中的Bean
  • Python酷库之旅-第三方库Pandas(218)
  • 2024强化学习的结构化剪枝模型RL-Pruner原理及实践
  • Tensorflow基本概念
  • Azure Machine Learning - 使用 Azure OpenAI 服务生成文本
  • vue打包完成后出现空白页原因及解决
  • 第二十五章 控制到 XML 模式的映射 - 将文字属性映射到 XML 模式
  • 学习mongoDB
  • 【6】PyQt信号和槽
  • Python语言基础学习大纲(由某大模型生成)
  • uniapp基于u-grid-item九宫格实现uCharts秋云图表展示
  • 软著项目推荐 深度学习的智能中文对话问答机器人
  • Qt之QCache和QContiguousCache
  • 第19章 正则表达式 - C++
  • Flink-执行拓扑图与作业调度
  • MacOS 14挂载NTFS 硬盘的最佳方式(免费)
  • CoreDNS实战(五)-接入prometheus监控
  • 【蓝桥杯选拔赛真题28】C++口罩分配 第十三届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析
  • JavaScript基础知识21——for循环
  • 分包(微信小程序)
  • 网络安全(三)-- 网络嗅探及协议分析技术
  • maven环境搭建
  • 如何使用llm 制作多模态
  • Spatial Data Analysis(三):点模式分析