1 skynet启动的第一个服务
我们知道,skynet
以服务(service
)为基础,那么,当我们输入指令> skynet examples/config
之后,skynet
启动的第一个服务会是什么呢?
这一点我们先看看最常用的配置文件,通常会有这么两行:
start = "main" -- main script
bootstrap = "snlua bootstrap" -- The service for bootstrap
其中,bootstrap
是指定启动的第一个服务:snlua
,及其参数:bootstrap
snlua
是skynet
内置的一个最常用的c服务
,以.so
的形式存在于cservice/
目录下,简单地说,就是用来启动一个lua服务。
snlua bootstrap
则是将bootstrap
作为参数传给snlua
服务。
snlua
的具体功能,可以看代码service_snlua.c
,简单地说,就是加载一些库,修改一些函数(coroutine.resume / coroutine.wrap
),切换分代CG等等。然后就调用./lualib/loader.lua
文件,将参数(bootstrap
)传入。
理论上,我们也可以配置成
bootstrap="snlua myBoot"
,使用我们自己的启动脚本,但没必要,skynet默认的bootstrap已经帮我们将事情都处理好了。
2 ./lualib/loader.lua做了些什么
loader.lua
可以接收多个参数,其中第一个参数是服务名,其他的是服务启动的参数。
loader
如何根据服务名来找到对应的入口文件呢?
答案是配置文件中的luaservice
,在示例的配置中,luaservice
长这样:
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua"
那么,skynet
会按顺序
依次查找文件service/bootstrap.lua
,test/boostrape.lua
,examples/bootstrap.lua
,test/bootstrap/init.lua
,找到第一个
存在的文件,然后调用这个文件。如果所有文件都不存在,则抛出错误。
在调用
bootstrap.lua
之前,如果配置文件配置了preload
,则会先调用这个preload
文件
理论上,我们也可以配置自己的
loader
文件,不一定要使用系统的loader.lua
,但这通常也是不必要的
3. bootstrap.lua又做了些什么
通过loader.lua
,我们找到了service/bootstrap.lua
这个文件,这里就是常用的skynet
的lua
服务写法:
local skynet = require "skynet"
skynet.start(function()
--...
skynet.exit()
end)
这里主要是启动了一些服务:
-
launcher
:用来启动、管理lua
服务,先启动这个服务,后续才能调用skynet.newservice
等函数来启动服务。 -
cdummy
:启动harbor
服务,基本没什么用 -
datacenterd
:数据中心,可以查询、存储一些key/value
-
service_mgr
:管理单例服务,skynet.uniqueservice
和skynet.queryservice
时使用。
启动完这些服务之后,就是启动main
服务了,即配置文件中start="main"
这里指定的服务名,就是我们自己的服务的入口了~
当bootstrap
做完所有事情之后,则调用skynet.exit
,结束bootstrap
服务。
如果配置文件的
harbor
大于0,则还会启动cmaster
和cslave
服务。这是早期的设计,后续skynet
已经不建议配置harbor
了。
如果配置文件配置了
enablessl
,这里还会启动相关的服务