skynet源码剖析
从每个细节入手,剖析skynet源码
Shonm
用blog记录点点滴滴。。。成长的轨迹一步一个印
展开
-
skynet.newservice的实现简析
使用过skynet的童鞋都知道,一般新启动一个服务是调用skynet.newservice函数。至于他的代码实现,相信没有多少人会去看,这篇文章会讲明白为什么skynet.newservice要这么实现。刚开始的时候,我以为sky.newservice只是启动了一个参数是lua文件名的snlua服务,例如skynet.newservice('room'),我天真的认为他的实现如下:loc...原创 2019-04-17 16:38:00 · 4515 阅读 · 0 评论 -
skynet 简单的消息执行流程情景分析
skynet.lua对比以前优化了一些函数,尤其是对协程的控制,使得消息的处理流程更加清晰。我们现在来一步步剖析这个消息执行流程,加深对skynet reactor模式的理解以及协程的应用。首先看服务的第一条消息是怎么产生,又是如何被处理的。在创建一个snlua服务后第一条消息靠什么来驱动呢?答案是靠自己(第一步还是得靠自己,然后别人才有机会接触你),看看下面的代码可以清楚的看到:int...原创 2019-04-17 12:47:01 · 2099 阅读 · 0 评论 -
skynet socket.lua 读写缓冲区剖析
这两天剖析了一下socket.lua,整体不是很难,主要是数据缓冲区的实现需要好好分析一下。这里读写数据也是用到了缓冲池的思想,为了更加直观的说明代码,还有方便测试,我去掉lua代码,把核心接口直接用C++实现了一遍:#include <stdio.h>#include <string.h>#include <vector>using std::...原创 2019-03-19 22:40:19 · 1758 阅读 · 0 评论 -
skynet lua与c交互相关函数
我们都知道skynet底层是用c实现的,逻辑层用lua实现。那么c底层是怎么样与lua层实现交互的呢?这篇文章将会讲解这方面的内容。系列文章中的skynet怎么启动lua文件讲到了skynet是如何启动lua代码的,无非是调用lua api加载lua文件。有个QQ群友问到c底层究竟是如何调用到lua层的回调函数的,正好这篇文章会分析这个。加载我们的lua逻辑文件后,一般lua 服务都会有一...原创 2019-02-28 14:52:50 · 1457 阅读 · 2 评论 -
skynet 服务的名字
skynet服务的名字我们在开发过程中会使用到,这篇文章试着讲解一下skynet服务名字的有关内容。首先每个服务在初始化的时候都会调用skynet_command(ctx, "REG", ...)。例如snlua服务调用了skynet_command(ctx, "REG", NULL),logger服务调用skynet_command(ctx, "REG", ".logger"),最终会调用到...原创 2019-02-26 14:54:05 · 1445 阅读 · 0 评论 -
skynet网络部分剖析(三) socket消息的转换
skynet所有的消息最终会被lua层捕获,socket消息也不例外。上篇讲到了skynet的网络模型及epoll,所有的消息都是在epoll中发出的。那么网络消息又是如何转换为skynet服务间的消息的呢?skynet将不同的网络消息分类,例如连接消息,socket读数据消息等等。socket消息转换为skynet服务间的消息在skynet_socket_poll函数中体现:int ...原创 2018-07-13 15:19:36 · 2069 阅读 · 0 评论 -
skynet网络部分剖析(二) reactor模型
skynet是基于reactor网络模型的,并且他的网络层使用单线程。因为云风大大认为即使是代码量稍大一些的单线程程序,也会比代码量较小的多线程程序更容易理解,出 bug 的机会也更少。而且经典的网络服务程序,如 redis nginx 并没有因为单线程处理网络 IO 而变现得不堪,反而有不错的口碑。既然是reactor模式,就必然有同步事件分离器Synchronous Event Demul...原创 2018-07-12 18:27:06 · 1777 阅读 · 0 评论 -
skynet网络部分剖析(一) socket的状态
最近看了一些开源的网络库源码,有libevent,muduo,redis,类nginx等等。再看skynet网络部分就觉得很容易了,因为他们都是基于reactor模式,套路都差不多。不过skynet的网络部分要稍微复杂点,因为他最终要面向的是lua逻辑端。为了让lua socket api这块设计的合理,好用,整个网络架构上相比前面介绍的网络框架会有点绕,比方说socket的状态,比其他框架要多出...原创 2018-07-12 13:31:42 · 2253 阅读 · 5 评论 -
skynet消息队列结构分析
队列一般可以用链表来模拟,用两个指针,分别指向头节点和尾节点。尾节点指向插入数据的方向,头节点指向消耗数据的方向。skynet全局消息队列也用到了上面的数据结构:struct message_queue { struct spinlock lock; uint32_t handle; int cap; int head; int tail; int release; int i...原创 2018-06-29 12:12:00 · 1967 阅读 · 0 评论 -
skynet 热更新
有了前面的 lua 热更新原理(一)作为铺垫,相信理解skynet热更新会容易点。但是有个问题是,skynet不能像前面讲的那样,重新require文件来达到热更的目的,为什么?出于效率的考虑,云风大大修改了lua的官方实现,require文件时会缓存之前的代码,再次require该文件,检测到有缓存是不会加载新的文件的。参见:CodeCache不过那个也可以通过选项来控制,调用sky...原创 2018-06-11 20:59:42 · 5227 阅读 · 1 评论 -
skynet debug_console源码分析
由于讲热更新的需要,先讲skynet控制台的用法。skynet 的控制台服务,可以很方便获取和调试 skynet中运行的数据,而且可以热更新代码。弄明白skynet控制台管理可以更好地使用skynet,甚至改进这个控制台服务,以满足不同业务需求。这个服务默认不会启动,需要你手动启动它,如下:skynet.newservice("debug_console", debug_port)他会启动debu...原创 2018-06-06 20:42:48 · 1137 阅读 · 0 评论 -
skynet watchdog,gate源码分析
前一篇skynet watchdog和gate讲解了watchdog和gate的流程图,这篇就代码剖析一下。watchdog和gate旨在简化网络模块的设计,在实际的项目中我们通常会都会用到这种模式 ,提高生产效率。前面讲的集群模块中也用到了这种模式。skynet中gate.lua文件实际上引用了gateserver.lua,他们共同构成了一个服务,消息的主体回调处理在gateserver...原创 2018-06-06 17:34:16 · 3058 阅读 · 0 评论 -
skynet 集群cluster初探
由于本人对集群这块应用的不多,现只对其内部调用机制作简单的剖析。集群源码包括两个文件cluster.lua和clusterd.lua。cluster.lua其实是对clustered.lua的api的封装。我们用到集群时只需要使用cluster.lua的api即可。使用集群时必须引用cluster.lua文件,他会单例启用clusterd服务。而clusterd服务最开始就会调用loadconfi...原创 2018-06-05 19:48:58 · 4874 阅读 · 0 评论 -
skynet 消息type, session, src, dest
我们写skynet回调函数时,一般的格式是:skynet.dispatch('xxx_type', function(session, address, command, ...) ... end)回调函数的包含了type,session,address等参数,那他们的作用是什么,怎么传递的呢?在c层处理消息时,调用的回调函数参数是:_cb(struct skynet_context * cont...原创 2018-06-04 16:42:52 · 1249 阅读 · 0 评论 -
skynet 服务相关api
1 启动服务相关我们都知道开启一个新服务的方式是skynet.newservice('name')。他的实现为:function skynet.newservice(name, ...) return skynet.call(".launcher", "lua" , "LAUNCH", "snlua", name, ...)end所有首先要开启launcher服务。其实launcher服务首先会在...原创 2018-06-01 18:09:03 · 1508 阅读 · 0 评论 -
skynet watchdog和gate
skynet lua层的基础讲解的差不多了.就剩下网络这一块了.网络这块比前面的复杂,也是skynet框架的精华所在,所以放在后面慢慢讲解.今天看了服务器与客户端交互常见的watchdog和gate模块,相当于封装了socket api的调用,程序只需要写发送和接收的逻辑即可,很是方便.下面是我花了一下午的时间,制作的UML时序图,可能不是很规范,但还算比较清晰.看到上面图,是不是感觉...原创 2018-04-19 21:05:21 · 2810 阅读 · 1 评论 -
skynet网络基础剖析
千呼万唤始出来,终于有时间开始分析skynet网络部分的代码了。skynet是个网络服务器框架,网络才是他的核心所在,读懂了网络模块的代码才算是对skynet有深入的了解。花了两天时间读了网络部分的代码,底层网络模型是基于epoll的,这个在llinux高并发上是最高效的模型。底层网络的各种操作或响应(诸如accept,msg,close)也是通过发送消息告知lua层的回调函数,这点与前面讲的...原创 2018-05-23 22:15:15 · 2814 阅读 · 0 评论 -
skynet lua层消息的执行顺序
前几篇讲解了服务之间互相发送消息,消息的挂起,恢复,fork等等,感觉还是有点搞不清他们之间是怎么协作的,例如fork产生的协程什么时候被调用,如果有多个fork又怎么被调用.这篇试着讲解一下.首先要明白的是,一般所有的lua层函数都是以协程的方式被执行的,包括fork产生的函数.除非你在skynet.start()之外调用函数.这点通过前面的分析可以知道. start()函数调用timeout产...原创 2018-04-15 17:12:30 · 1740 阅读 · 0 评论 -
skynet 定时器sleep与fork
在前面的几篇中定时器其实我们已经应用过了,入口函数就是靠定时器驱动的,只不过他的定时为0.参见skynet lua业务逻辑的启动--skynet.start().在后面的服务与服务交互中,为了保证在A服务call B服时,B服务已经启动,我们特意在A服务call前执行了一个无意义的循环.这节中的定时器就可以解决这个问题,调用skynet.sleep(xxx)就可以让协程挂起.我们看看slee...原创 2018-04-03 20:15:56 · 4044 阅读 · 1 评论 -
skynet call的实现--服务与服务的交互
在实现业务逻辑的过程中,各个逻辑一般会抽象成一个服务,例如游戏中的登录服务,访问数据库服务,创建房间服务等等.服务与服务之间肯定是要通信和交互的,例如登录的时候要请求数据库验证.skynet是怎么实现两个服务的通信和交互的呢?为了突出主干,我简化了lua服务代码,A服务调用B服务:A服务代码(bootstrap.lua):skynet.start(function() local ad...原创 2018-04-02 17:07:22 · 3635 阅读 · 0 评论 -
skynet lua业务逻辑的启动--skynet.start()
上两篇skynet主体流程, skynet怎么启动lua文件介绍了skynet代码的主体流程,还有怎么启动lua逻辑.我们知道skynet业务逻辑都是在lua里写的,这样大大提高了开发效率,而且使热更新成为可能,究竟lua层是怎么保证逻辑正常运行,一个服务在lua层的表现形式又是怎么样的呢?这篇将为您讲解.一个服务在lua层的入口是skynet.start(),他的实现为:funct...原创 2018-04-02 11:09:50 · 3818 阅读 · 0 评论 -
skynet怎么启动lua文件
前篇在skynet主体流程中说到,在slua服务初始化的时候会给自己的消息队列发送一条消息,内容为bootstrap。当消息被捕获并执行时,会调用slua的回调函数_launch,他是在模块初始化中指定的。我们来看看这个回调函数:static int_launch(struct skynet_context * context, void *ud, int type, int sessio...原创 2018-03-29 11:38:12 · 2925 阅读 · 0 评论 -
skynet加载配置文件
看了skynet加载配置的地方,竟然发现好多知识点,记录下.skynet的配置文件是通过命令行传入到进程的,这个比较明了. 仔细读了一下这块代码,发现有不少细节,而且,有些lua函数竟然很少用过,下面就这块代码分析一下.intmain(int argc, char *argv[]) { const char * config_file = NULL ; if (argc > ...原创 2018-05-22 17:17:39 · 2603 阅读 · 0 评论 -
skynet主体流程
1 初始化工作 锁,线程,信号的处理。2 加载配置 skynet会开启一个全局专门用来加载配置的lua虚拟机, 虚拟机加载配置文件,将配置项填充到一个配置数据结构skynet_config中,具体过程请看下篇skynet加载配置文件。3 调用skynet_start(skynet_config*)启动日志模块a) 根据skynet_config初始化模块路径,time,s...原创 2018-03-29 11:35:34 · 4125 阅读 · 0 评论