一:启动过程,参考http://www.jianshu.com/p/f7e59559a975
通过解析配置文件来启动服务器
例如简单的一个命令./skynet examples/config,就是解析config文件配置服务器的参数与相关进程的启动顺序,这可以满足我们对服务器的需要。
看我当时给出的注释:
这个配置文件实际上就是一段 lua 代码,通常,我们以 key = value 的形式对配置项赋值。从注释可以看出来。
skynet 在启动时,会读取里面必要的配置项,并将配置项以字符串形式保存在 skynet 内部的 env 表中。这些配置项可以通过 skynet.getenv 获取。
下面看看bootstrap要启动的是哪些服务
首先是
先启动launcher服务。skynet.launch(...)主要通过skynet.core模块中的command()函数执行可变参数中的服务,并返回为服务开辟的地址。skynet.name()函数其实就是给返回的地址起一个名字,这个函数里面会先调用globalname()函数去判断在全局表中是否有这个名字,有的话就直接为这个地址设置名字。没有的话还要调用harbor.lua模块中的harbor.globalname函数去注册地址,设置名字。
下面要判断harbor是0还是非0,因为这个会决定是否启动单节点模式下。此时 master 和 address 以及 standalone 都不能设置。可以从代码中看出来
第一句就是断言standalone 等于nil,然后在全局表中设置standalone为true。然后就是调用pcall函数去调用skynet.newservice()函数启动cdummy服务。问题是这是一个什么服务。看cdummy.lua模块中的start()函数,主要是调用skynet.dispatch函数调度新服务的启动,这个服务好像什么也没做?最后返回一个服务地址,并为该地址命名cslave (也就是说这个cslave服务无事可做?)
非0
启动cmaster服务,主要负责监听端口号,并负责握手连接。看看源码
调用socket.listen()函数监听master_addr,master_addr是standalone的地址。socket.listen()函数其实调用了socketdriven C函数(在lua-socket.c中的luaopen_socketdriver函数,返回LUAMOD_API)中的llisten()函数,监听成功就返回1。接着cmaster会调用socket.start()函数。
这个master_addr是0.0.0.0:2013中心节点
这个函数调用socketdriver的lstart()函数,做的工作是获取skynet中socket的上下文,为下面调用connect()函数做准备,这个connect函数会调用作为参数传进来的回调函数,用的是tcp连接。connect函数会唤醒一个休眠的协程完成连接操纵,返回连接id。
接下来会启动cslave服务。这个服务做的事情有点多,主要是与cmaster建立连接。先看看他拿了一些配置项
master地址,就是我们认为设置要连接的地址;
slave_address地址,这里的配置文件设置的地址与master一样,端口号不一样,不是太懂
可以看到开始监听slave_address地址。接着调用socket.open()函数连接到master_addr
driver.connect()函数返回的是socket池中的id,表示连接的套接字已经设置好,可以进行连接。接着connect()函数就唤醒休眠的协程找到socket池中的套接字进行连接。这里会回调cmaster中start函数里面的回调函数。cmaster会拿到driver.connect()函数返回的socket池中的id,然后准备与该套接字进行连接
然后会进行握手尝试,返回的是slave_id和slave_addr。handshake()函数做的事情是调用read_pakage()函数,从之前的套接字中读取数据,也就是cslave中driver.connect()返回的socket池中的id,拿到要连接的slave_id, slave_addr,然后判断这个slave是否已经注册,没有的话就调用report_slave()函数向slave服务发送handshake回应
然后注册slave_node。如果注册成功的话,为slave创建监控进程monitor_slave
注意handshake过程中cslave也对cmaster作出回应
这里也可以看到slave也为master创建monitor_master()进程。这里是双方相互监听,相互通过套接字读取数据
再回到bootstrap.lua中,还要开启datacenterd服务。来看看这个服务做了什么。
这个服务大概就是调用skynet.dispatch()函数通过解析命令对数据进行读写更新。
最后还开启了一个service_mgr服务,注册.service服务。
然后就是我们自己定义的main或start服务了。
sprotoloader.lua 读取协议文件并注册该协议,通过下标加载协议。
proto.lua是客户端跟服务器之间沟通的消息格式,也就是一个协议。
协议的解析的实现在sprotoparser.lua,有点难看懂,后面看懂了再说
sproto.lua是跟具体的package建立协议