Skynet配置文件

Skynet配置文件_第1张图片
Skynet启动流程

Skynet是由一个或多个进程构成的,每个进程被称为一个Skynet节点。

启动Skynet节点时需使用 skynet config_filename命令,运行启动指令时需要传入一个配置文件的文件名config_filename作为启动参数,Skynet会读取配置文件中参数完成初始化等操作。

Skynet进程启动后,首先会读取config_filename配置文件,然后解析这个Lua文件,再把相关配置信息设置到Lua的环境变量中。

以源码为例,Skynet启动时使用example文件夹下的config.lua配置文件。

./skynet example/config

查看skynet_main.c文件中C代码的main入口函数,位于skynet-src/skynet_main.c文件中。

skynet_main.c文件是干什么用的呢?

skynet_main.c主要是设置Lua的环境、设置默认的配置、打开配置文件、修改默认配置,最后会调用skynet_start函数。

skynet_start函数位于skynet-src/skynet_start.c文件中,其主要作用是初始化Skynet中的各个模块,包括horbor节点、handle服务ID、mq消息队列、module模块加载动态链接库、timer时钟、socket套接字以及加载部分服务的logger日志服务、master主服务、harbor节点服务、snlua加载Lua模块的服务等。最后启动线程,包括_monitor_timer_socket,并根据线程数量启动多个工作线程。

int main(int argc, char *argv[])
{
  const char *config_file = NULL;//定义配置文件路径
  if (argc > 1)
  {
    config_file = argv[1];//保存配置文件名称
  }
  else
  {
    fprintf(stderr, "Need a config file. Please read skynet wiki : https://github.com/cloudwu/skynet/wiki/Config\n"
            "usage: skynet configfilename\n");
  }
  sigign(); // 设置信号处理函数
  env_env_init();//初始化保存配置文件的环境,该函数在env.c文件中,与之对应的是skynet_env.c文件。
}

需要注意的是配置文件的路径会保存到config_file指针上,那么它是如何加载的呢?这一点要涉及到Lua C API。

打开example/config文件,了解下配置文件中的各个参数。

$ cat example/config.lua
include "config.path"

-- preload = "./examples/preload.lua"   -- run preload.lua before every lua service run
thread = 8
logger = nil
logpath = "."
harbor = 1
address = "127.0.0.1:2526"
master = "127.0.0.1:2013"
start = "main"  -- main script
bootstrap = "snlua bootstrap"   -- The service for bootstrap
standalone = "0.0.0.0:2013"
-- snax_interface_g = "snax_g"
cpath = root.."cservice/?.so"
-- daemon = "./skynet.pid"

根据config.lua配置文件可以发现,它首先需要加载当前文件夹下的config.path.lua路径配置文件。

include "config.path"
$ cat example/config.path.lua
root = "./"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua;"..root.."workspace/?.lua"
lualoader = root .. "lualib/loader.lua"
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
lua_cpath = root .. "luaclib/?.so"
snax = root.."examples/?.lua;"..root.."test/?.lua"

Skynet是如何读取配置文件的呢?

启动Skynet时传入配置文件的example/config.lua,实际上会被当做一段Lua代码加载并以key = value键值对的形式为配置项赋值。

Skynet中必要的配置会保存在struct skynet_config config结构体中,暂时不用的配置项会以字符串的形式保存在Skynet内部的env表中,用户自定义的配置可通过skynet.getenv获取。

Skynet配置参数可以分为哪几类呢?

  • 必要配置项
  • 可选配置项
  • Lua环境配置项
  • 集群配置项
  • 用户配置项

必要配置项

thread

thread = 8

thread表示启动的工作线程数量,通常不要将工作线程的数量设置的超过实际拥有的CPU的核心数量。

可以将thread配置到SKYNET_THREAD环境变量中

thread = $SKYNET_THREAD

bootstrap

bootstrap = "snalu bootstrap"

Skynet中logbootstrap是启动时的两个服务,默认的boostrap配置项为snlua bootstrap,意味着Skynet会启动snlua这个服务,并将bootstrap作为参数传递给它。

bootstrap设置Skynet启动时的第一个服务以及其启动参数,默认配置为snlua bootstrap,即启动一个名为bootstraplua服务,通常指的是service/bootstrap.lua

snlua是Lua沙盒服务,bootstrap会根据luaservice匹配到最终Lua脚本。若按默认配置,这个脚本是service/bootstrap.lua

bootstrap最后一行会从config中读取start配置项,这个配置项才是用户定义的启动脚本。作为用户定义的服务启动入口脚本运行,启动成功后则会把自己退出。

其实bootstrap是Skynet启动的第二个服务,第一个服务应该是logger,为什么这么说呢?

Skynet通过skynet_context_new函数实例化一个服务,它首先会从logger.so文件中把模块加载进来。当启动logger服务完成后,接下来要启动的服务才是bootstrap,不过在这之前需要先加载snlua模块,因为所有的Lua服务都属于snlua模块的实例。和加载logger服务类似,Skynet先会把snlua.so文件作为模块加载进来,然后调用模块自身的_create函数来产生一个snlua实例(service_snlua.c)。产生snlua实例的目的在于生成一个新的Lua虚拟机,也就是Lua的沙盒环境。这一点非常重要,因为所有的Lua服务都是在一个独立的Lua虚拟机中运行的。

skynet_context_new函数是干什么用的呢?

在C语言实现中skynet_context_new函数位于skynet-src/skynet_server.c文件中,skynet_context_new函数主要用来实例化服务动态链接库中的_create_init函数,以及为服务创建一个私有的消息队列,并填充到struct skynet_context结构中。

start

start设置的是bootstrap的最后一个节点,也就是将要启动的Lua服务,即定制Skynet节点的主程序,默认为main。简单来说,就是启动main.lua这个脚本。

这个Lua服务的路径由luaservice指定。简单来说,mainbootstrap结束后启动的用户自定义服务,可以把它当作是启动项。

cpath

cpath = skynet_root.."cservice/?.so"

cpath设置使用C编写的服务模块的位置,通常指cservice目录下.so文件,若系统的动态库不是以.so为后缀,只需做相应的修改,这个路径可以配置多项,并以;分割。

start = "main"

日志配置

logger

logger = nil

logger决定了Skynet内置的skynet_error这个C语言API将日志信息输出的位置。

logger设置为nil则表示输出到标准输出,可以指定一个路径和文件名用来将日志输入到文件中。

logservice

logservice = "logger"

logservice配置用户定制的日志服务,可参考service_logger.c来实现。如果希望使用Lua编写这个服务,可设置为snlua,然后在logger配置项中设置具体的Lua服务的名字,可参考example/config.userlog文件。

logpath

logpath = ""

logpath配置日志保存的文件名,当运行时为某个服务打开log时,这个服务所有的输入消息都会被记录到此目录下,文件名为服务地址。

网络配置

harbor

harbor = 0

Skynet可以启动多个节点,不同节点内的服务地址是相互唯一的,服务地址是一个32bit的整数。同一进程内的地址是高8位相同,低8位区分一个服务处理哪一个节点。

每个系欸但中都有一个特殊的服务叫做handor(港口),当一个消息的目的地的高8位和当前节点不同时,消息被投递到harbor服务中,最后通过TCP连接传输的目的地节点的harbor服务。

harbor可以是1到255之间的任意整数,一个Skynet网络最多支持255个节点。每个节点必有一个唯一的编号。如果harbor为0则表示Skynet工作在单节点模式下(单点模式),此时masteraddressstandalone都不必设置。

master

不同的Skynet节点之间是如何建立其网络的呢?

这依赖一个叫做master的服务,master服务可以单独作为一个进程,也可以附属在某个Skynet节点内部(默认配置)。

master服务会监听一个端口(在配置文件中的standalone选项设置),每个Skynet节点都根据配置中的master去连接最终一个有5个节点的Skynet网络。

Skynet配置文件_第2张图片
Skynet网络
master = "127.0.0.1:2013"

master设置Skynet控制中心的地址和端口,若已经配置了standalone选项,那么此配置项和standalone相同。

address

address = "127.0.0.1:2526"

address设置当前Skynet节点的地址和端口,方便其它节点进行组网。即使只有一个Skynet节点也需要开启控制中心,并额外配置节点的地址和端口。

standalone

standalone = "0.0.0.0:2013"

如果把Skynet进程作为主进程启动,由于Skynet可以由分布在多台机器上的多个进程构成。那么就需要配置standalone这个选项,表示这个进程是主节点,它需要开启一个控制中心,监听一个端口,让其它节点接入。

集群配置

cluster

cluster = ""

cluster配置决定了集群配置文件的路径

Lua环境配置项

Lua服务由snlua提供,snlua会查询一些配置项以加载Lua代码。

lualoader

lualoader = skynet_root.."lualib/loader.lua"

lualoader用于配置调用哪一段Lua代码加载Lua服务,通常配置为lualib/loader.lua,由这段代码解析服务名称,进一步加载Lua代码。

snlua会将核心配置项取出,放置在初始化好的Lua虚拟机的全局变量中。

  • SERVICE_NAME 服务名称
  • LUA_PATH 配置文件中的lua_path
  • LUA_CPATH 配置文件中的lua_cpath
  • LUA_PRELOAD 配置文件中的lua_preload
  • LUA_SERVICE 配置文件中的luaservice

luaservice

luaservice指定了Lua服务代码所在的位置,可配置多项以分号;分隔。

如果在创建Lua服务时是以一个文件夹而非单个文件,那么最终找到的路径还是会被添加到package.path中。

lua_path

lua_path = skynet_root.."lualib/?.lua;"..skynet_root.."lualib/?/init.lua"

将添加到package.path中的路径提供给require调用

lua_cpath

lua_cpath = skynet_root.."luaclib/?.so;"

将添加到package.cpath中的路径提供给require调用

preload

preload = ""

在设置完package中的路径后,加载Lua服务代码前,loader会尝试先运行一个preload指定的脚本,默认为空。

snax

snax = ""

使用snax框架编写的服务的查找路径

其它配置

root

root = "./"

root表示根目录是Skynet启动时的目录,用于设置当前项目的根目录。

skynet_root

skynet_root = "lib/skynet/"

设置Skynet的根目录

daemon

daemon = "./skynet.pid"

daemon可以以后台模式启动Skynet,注意需同时配置logger项的输出log

最佳实践

$ vim config/config_linux.tpl
root="../"
thread = 4

logger = nil
logpath = "."

harbor = 0

-- main script
start = "main"  

-- The service for bootstrap
bootstrap = "snlua bootstrap"   

luaservice = "../service/?.lua;../business/?.lua;../libs/service/?.lua;"
lualoader = "../libs/lualib/loader.lua"
lua_path = "../lualib/?.lua;../libs/lualib/?.lua;../libs/lualib/?/init.lua;../business/?.lua;../model/?.lua;../const/?.lua"
lua_cpath = "../luaclib/?.so;../libs/luaclib/?.so"
cpath = "../libs/cservice/?.so"

-- daemon
-- daemon = "../game.pid"

-- debug_console
debugport = 9000  

wshost = "0.0.0.0:8888"

httpport = 9999

db_mysql_master = '{
    "host":"",
    "port":3306,
    "user":"",
    "password":"",
    "database":""
}'

db_mysql_slave = '[
    {
        "host":"",
        "port":3306,
        "user":"",
        "password":"",
        "database":""
    }
]'

db_redis = '[
    {
        "host":"",
        "port":6379,
        "db":4,
        "auth":""
    }
]'

http_snlua_num = 10
mysql_snlua_num = 2
redis_snlua_num = 10

未完待续...

你可能感兴趣的:(Skynet配置文件)