首页 > 其他分享 >关于Skynet

关于Skynet

时间:2024-11-25 18:29:47浏览次数:9  
标签:服务 队列 Lua 关于 Skynet 消息传递 消息

Skynet 设计目标

Skynet 的核心目标是提供一个轻量级、高性能的服务框架,专注于 多核利用模块化设计,避免传统多线程模型的复杂性,为高并发场景(如游戏服务器)提供可靠的解决方案。它利用 Lua 和 C 的结合,将服务抽象为独立模块,通过消息队列进行通信。

核心解决的问题

  • 服务的隔离与独立运行:通过 Lua 沙盒和轻量级服务模型,每个服务在独立的 Lua 环境中运行,减少多线程模型中的竞争与锁问题。
  • 高效消息通信:使用单向消息传递机制,实现服务间的非阻塞通信,保障线程安全。
  • 服务调度与资源管理:服务仅在处理消息时消耗资源,空闲服务零 CPU 占用。
  • 高性能数据传递:通过零拷贝机制和优化的内存管理,实现同一进程内的高效数据交换。

不解决的问题

Skynet 核心框架明确不涉及以下内容,这些问题交由上层服务或用户代码处理:

  • 进程间通信:核心层仅支持单进程内服务通信,集群通信通过 harbor 服务完成。
  • 错误隔离与自动恢复:服务的健壮性由上层逻辑保障,框架不提供自动化的错误隔离机制。
  • 复杂协议支持:不强制统一数据编码格式,也不内置 RPC 协议,支持用户自定义协议。
  • 跨节点服务同步:集群服务的管理(如全局名字服务)需要独立实现。

设计特点

1. 轻量化和高性能

  • 核心代码精简:核心层仅约 3000 行 C 代码和少量 Lua 代码,便于理解与维护。
  • 高效消息调度:通过两级消息队列(全局队列 + 服务私有队列),优化消息处理的公平性和效率,避免资源饥饿问题。
  • 零拷贝优化:在服务间传递数据时,可以选择零拷贝机制,提升性能。

2. 模块化架构

  • 服务(Service)抽象:每个服务独立运行,拥有唯一的数字标识(handle),服务之间通过消息通信,解耦逻辑。
  • 服务生命周期:服务在接收消息时激活,消息处理完成后挂起,不占用 CPU。
  • 动态加载与扩展:支持 C 模块的动态加载,可轻松扩展功能。

3. 灵活的消息系统

  • 单向消息传递:消息由发送者生成,通过框架传递到接收者,不需要建立持续连接。
  • Session 标识:通过 session 标识消息请求和响应,支持异步调用和多协议协作。
  • 消息类型(Type):通过 type 参数区分消息协议组别,便于支持多种通信协议。

4. 多语言支持

  • Lua 语言:作为默认的逻辑层语言,Lua 的沙盒环境保证服务隔离,协程支持简化异步逻辑。
  • 动态语言兼容性:框架可以嵌入其他动态语言(如 Python),并允许多种语言共存。

5. 集群与扩展

  • 跨节点通信:通过 harbor 服务支持分布式部署,每个节点分配唯一的 harbor id,消息传递透明化。
  • 全局名字服务:通过 master 服务同步全局名字和节点地址。
  • 组播支持:内置组播机制,优化高频多目标消息的发送。

技术实现

1. 消息模型

  • 每个消息由以下信息组成:
    struct skynet_message {
        uint32_t source;  // 消息源
        int session;      // 会话标识
        void * data;      // 数据指针
        size_t sz;        // 数据大小
    };
    
  • 消息传递通过全局队列和服务队列实现:
    • 全局队列存储不为空的服务队列。
    • 服务队列存储该服务的所有未处理消息。

2. 服务的隔离与通信

  • 服务隔离:每个服务运行在独立的 Lua 状态中,通过消息传递进行通信。
  • 消息安全性:Skynet 保证同一时间一个服务仅有一个工作线程处理消息,无需额外的线程安全措施。

3. 数据包管理

  • 默认消息传递中,数据包由发送方分配内存,接收方释放。
  • 提供可选的零拷贝传递模式,避免频繁内存分配和数据复制。

4. Lua 支持

  • Lua 层封装了底层 API,并通过协程实现异步处理,隐藏回调细节。
  • 提供内置消息协议(Lua 协议),支持直接序列化 Lua 数据类型。

5. 网络支持

  • Gate 服务:处理外部 TCP 连接,负责协议解析和数据转发。
  • Connection 服务:用于建立与外部服务的 TCP 连接,支持第三方库的接入。
  • 自定义分包协议:用户可以实现适配不同协议的 Gate 和 Connection 模块。

应用场景

Skynet 的设计目标使其非常适合以下应用场景:

  1. 游戏服务器
    • 大型多人在线游戏(MMORPG)。
    • 卡牌游戏、MOBA 游戏等高并发类型。
  2. 分布式系统
    • 分布式微服务架构。
    • 高性能通信中间件。
  3. 轻量级服务框架
    • Web 服务器。
    • 数据处理与实时计算服务。

Skynet 的设计精髓在于简洁、模块化和高性能。其利用 Actor 模型,结合 Lua 的灵活性和 C 的性能,提供了适合高并发场景的解决方案。通过明确核心职责与上层职责的划分,Skynet 避免了框架本身的复杂性,同时给开发者留下了巨大的扩展空间。

标签:服务,队列,Lua,关于,Skynet,消息传递,消息
From: https://blog.csdn.net/shinecox/article/details/144034639

相关文章

  • 关于STM32存储、内存分析(为何从0x8000起始)
    关于图上的几个问题(图从左往右看)1.为什么STM32的理论地址范围(寻址范围)为4G?STM32的地址总线为32位,32位可以理解为物理的引脚,32只引脚通过拉高拉低,也就是选择0或者1,32位2进制=2的32次方=4294967296组地址,一个地址对应一个字节,即:4294967296字节=4194304KB=4096MB=4GB地址总线......
  • 关于测试你混淆appium、adb、pytest了吗?
    1.区别功能重点ADB:侧重于安卓设备的调试和基本操作。它能与安卓设备进行底层交互,如文件传输、应用安装/卸载、设备状态查看等。例如,通过adbpush命令将本地文件推送到安卓设备,或者使用adblogcat获取设备的日志信息,这些操作主要是针对设备本身的管理和调试。Appium:专注于......
  • 关于日期的处理经验FAQ
    一、说明在日常的数据加工、搬迁等操作过程中,账期字段是一个无法避免的字段,在灵镜报表平台中需要使用账期字段(必须是date类型)来进行报表的筛选年、月、日,但是在梧桐数据库中,date的数据格式为YYYY-MM-DDHH24:MI:SS类型,固涉及到一些相应的转换。二、部分使用经验Q1:在不同数......
  • 关于train, evaluate 和 作图——dymean3
    TMscore从代码实现来看,这里的TMscore计算是通过调用外部的TMscore可执行程序完成的,输入的PDB文件包含了原子的三维坐标信息。那么具体答案可以分以下几个方面来分析:1.是否只对CA坐标进行计算答案:否。TMscore通常会基于整个PDB文件中所有原子的坐标计算分子结构......
  • 关于重复造轮子这件事你是怎么理解的?
    在前端开发领域,“重复造轮子”指的是重新开发已经存在且成熟的解决方案或工具,而不是直接使用它们。这通常会浪费时间和资源,并且可能导致代码质量下降、维护成本增加以及与现有生态系统的不兼容。然而,“重复造轮子”并非总是坏事,在某些情况下,它可能是合理的,甚至是有益的。关键在于......
  • 关于电机(马达)在高速运转的时候可能影响单片机电路的原因和解决方法
    问题:我买了一个马达,然后写了用开关来调节PWM占空比然后给TB6612输入PWM来改变马达转速的代码,每按一次按键PWM+10%,不接马达的时候能正常加,一连上马达时,加到20%马达刚好转起来后我的PWM占空比就迅速疯狂加10然后到100爆了后然后回到0,马达转动还会影响我的外部中断?可能原因:有可......
  • Qt关于窗口一直调用paintEvent的踩坑实录
    首先看以下代码:voidItemBlockWidget::paintEvent(QPaintEvent*ev){//先调用父类的paintEvent以执行默认绘制行为QWidget::paintEvent(ev);qDebug()<<"ItemBlockWidget重绘";QStyleOptionopt;opt.initFrom(this);QPainterp(this);s......
  • 【JavaScript】关于对象解构赋值
    概念对象解构赋值是JavaScript中的一种语法特性,它提供了一种简洁的方式来从对象中提取属性值,并将这些值赋给变量。这种方式使得代码在处理对象数据时更加直观和高效,避免了传统的通过对象属性访问(如object.property)来逐个获取和赋值的繁琐过程。对象就像是一个装满各种......
  • 关于C语言 字符串(字符数组)s
    关于charC语言中的字符型用关键字char表示,它实际存储的是ASC码。字符常量可以用单引号法表示。在语法上可以把字符当做int型使用。字符串的实际长度每次存储字符串,应多分配字符个数加1,因为C语言的字符串被读取后会添加空字符"\0"结尾例如:存储"2357"到chara[20]中,a会存储......
  • 关于vue生命周期理解示例代码
    在业务运作时,特定的逻辑代码,需要在特定的阶段去执行,所以需要理解Vue的生命周期,以及各个周期内的方法,才能明确业务代码的编写概述:Vue生命周期,指一个vue实例从创建到销毁的过程。分为四个阶段:①创建-->②挂载-->③更新-->④销毁①创建阶段  拿到数据准备好,进行响应式处理......