skynet源码学习-skynet_main入口
- 核心功能与启动流程
- Shell脚本启动示例
- main函数参数处理
- 其他相关联函数解析
- 1. 配置加载器解析
- 2. 环境变量设置
- 3. 配置解析函数
- 核心配置项解析
- 典型配置文件分析
- 服务启动与运行
- 核心服务启动流程
- 完整启动时序图
核心功能与启动流程
Skynet 的启动入口负责整个框架的初始化和配置加载,其工作流程如下:
Shell脚本启动示例
#!/bin/bash
./skynet /path/to/config.lua
main函数参数处理
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");return 1;}// 全局初始化skynet_globalinit(); // 初始化全局资源skynet_env_init(); // 初始化环境变量系统//信号处理sigign(); // 忽略SIGPIPE信号,防止网络断开导致进程退出struct skynet_config config;#ifdef LUA_CACHELIB// init the lock of code cacheluaL_initcodecache();
#endif// 创建Lua虚拟机struct lua_State *L = luaL_newstate();luaL_openlibs(L); // 加载Lua标准库// 加载并执行配置加载器int err = luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");assert(err == LUA_OK);lua_pushstring(L, config_file);err = lua_pcall(L, 1, 1, 0); // 执行配置加载if (err) {fprintf(stderr,"%s\n",lua_tostring(L,-1));lua_close(L);return 1;}// 这里处理将lua配置加载并设置到env环境变量中_init_env(L);lua_close(L);// 配置解析处理config.thread = optint("thread",8); // 默认8线程config.module_path = optstring("cpath","./cservice/?.so");config.harbor = optint("harbor", 1); // 默认节点ID=1config.bootstrap = optstring("bootstrap","snlua bootstrap");config.daemon = optstring("daemon", NULL); // 守护进程配置config.logger = optstring("logger", NULL); // 日志文件config.logservice = optstring("logservice", "logger"); // 日志服务config.profile = optboolean("profile", 1); // 默认开启性能分析skynet_start(&config); // 启动skynet核心skynet_globalexit(); // 释放全局资源
}
其他相关联函数解析
1. 配置加载器解析
static const char * load_config = "\local result = {}\n\local function getenv(name) return assert(os.getenv(name), [[os.getenv() failed: ]] .. name) end\n\local sep = package.config:sub(1,1)\n\local current_path = [[.]]..sep\n\local function include(filename)\n\local last_path = current_path\n\local path, name = filename:match([[(.*]]..sep..[[)(.*)$]])\n\if path then\n\if path:sub(1,1) == sep then -- root\n\current_path = path\n\else\n\current_path = current_path .. path\n\end\n\else\n\name = filename\n\end\n\local f = assert(io.open(current_path .. name))\n\local code = assert(f:read [[*a]])\n\code = string.gsub(code, [[%$([%w_%d]+)]], getenv)\n\f:close()\n\assert(load(code,[[@]]..filename,[[t]],result))()\n\current_path = last_path\n\end\n\setmetatable(result, { __index = { include = include } })\n\local config_name = ...\n\include(config_name)\n\ -- 加载主配置文件setmetatable(result, nil)\n\return result\n\
";
配置加载器是一个Lua代码字符串,核心功能:
- 支持include指令嵌套配置文件
- 支持$VAR形式的环境变量替换
- 构建配置表并返回
2. 环境变量设置
static void
_init_env(lua_State *L) {lua_pushnil(L); /* first key */while (lua_next(L, -2) != 0) {int keyt = lua_type(L, -2);if (keyt != LUA_TSTRING) {fprintf(stderr, "Invalid config table\n");exit(1);}const char * key = lua_tostring(L,-2);// 根据类型设置环境变量if (lua_type(L,-1) == LUA_TBOOLEAN) {int b = lua_toboolean(L,-1);skynet_setenv(key,b ? "true" : "false" );} else {const char * value = lua_tostring(L,-1);if (value == NULL) {fprintf(stderr, "Invalid config table key = %s\n", key);exit(1);}skynet_setenv(key,value);}lua_pop(L,1);}lua_pop(L,1);
}
3. 配置解析函数
- optint - 解析整数配置
static int optint(const char *key, int opt) {const char * str = skynet_getenv(key);if (str == NULL) {// 设置默认值char tmp[20];sprintf(tmp,"%d",opt);skynet_setenv(key, tmp);return opt;}return strtol(str, NULL, 10); // 转换字符串为整数
}
- optboolean - 解析布尔配置
static int optboolean(const char *key, int opt) {const char * str = skynet_getenv(key);if (str == NULL) {// 设置默认值skynet_setenv(key, opt ? "true" : "false");return opt;}return strcmp(str,"true")==0; // 检查是否为"true"
}
- optstring - 解析字符串配置
static const char * optstring(const char *key,const char * opt) {const char * str = skynet_getenv(key);if (str == NULL) {if (opt) {skynet_setenv(key, opt); // 设置默认值opt = skynet_getenv(key);}return opt;}return str;
}
核心配置项解析
skynet_config结构
struct skynet_config {int thread; // 工作线程数const char *module_path; // C服务模块路径int harbor; // 节点IDconst char *bootstrap; // 引导服务const char *daemon; // 守护进程配置const char *logger; // 日志文件const char *logservice; // 日志服务int profile; // 性能分析开关
};
典型配置文件分析
config.lua示例
-- 基础配置
thread = 8
harbor = 1
daemon = "./skynet.pid" -- 守护进程模式
logger = "logs/error.log" -- 错误日志-- 服务路径配置
cpath = "./cservice/?.so" -- C服务路径
lualoader = "./lualib/loader.lua" -- Lua加载器-- 引导服务
bootstrap = "snlua bootstrap" -- 启动引导服务
start = "main" -- 主入口脚本-- 自定义配置
mysql_host = "$DB_HOST" -- 使用环境变量
cluster_nodes = {"node1","node2",include "nodes.lua" -- 包含子配置
}