系统环境:Ubuntu
框架地址:
# 安装git
$ sudo apt-get update
$ sudo apt-get install git
# 安装⽀持库
$ sudo apt-get install build-essential libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip
# git克隆项⽬
$ git clone github/cloudwu/skynet.git
# 安装 autoconf
中航工业航宇救生装备有限公司$ sudo apt-get install autoconf
# 安装 realine-devel
$ sudo apt-get install libreadline-dev
# 编译源码
$ cd skynet
$ sudo make linux
$ ./skynet example/config
运⾏Skynet客户端
# 终端下编译Lua虚拟机成功后⽣成lua可执⾏⽂件
$ cd ./3rd/lua/
$ make linux
# 返回skynet根⽬录下运⾏客户端脚本
$ cd ../../
$ ./3rd/lua/lua example/client.lua
安装Lua5.3
$ lua -v
Lua 5.1.4 Copyright (C) , PUC-Rio
$ which lua luac
/usr/bin/lua
/
usr/bin/luac
$ wget /ftp/lua-5.3.
$ tar -zxvf lua-5.3.
$ cd lua-5.3.5
$ make linux test
$ make install
$ yum install libtermcap-devel ncurses-devel libevent-devel readline-devel
$ make linux
$ make linux install
配置Lua环境变量
$ sudo rm -rf /usr/bin/lua*
除铁
$ sudo ln -s /home/jc/projects/lua/lua-5.3.5/src/luac /usr/bin/luac
$ sudo ln -s /home/jc/projects/lua/lua-5.3.5/src/lua /usr/bin/lua
$ lua -v
Lua 5.3.5 Copyright (C) , PUC-Rio
安装Skynet
$ sudo yum -y install curl curl-devel readline-devel ncurses-devel autoconf gcc-c++ git $ git clone [github/cloudwu/skynet.git](github/cloudwu/skynet.git) $ cd skynet
$ make install
$ ./skynet example/config
⽬录结构
Skynet⽬录结构
3rd 第三⽅代码,包括lua和jemalloc等。
lualib 使⽤Lua编写的库
lualib-src 使⽤C编写并封装给Lua使⽤的库
service 使⽤Lua编写的服务模块
service-src 使⽤C编写的服务模块
skynet-src Skynet核⼼代码
Skynet⽬录结构
Skynet启动
Skynet由⼀个或多个进程构成,每个进程⼜称为Skynet节点。Skynet节点的启动⾸先需要配置⽂件config⽀持,分析实例example⽂件夹下提供的config配置⽂件会发现它是Lua代码,并以key-value形式进⾏赋值。Skynet启动时会读取必要配置项,其他配置项以字符串的形式存⼊env环境表中,所有配置项可通过v的⽅式获取。
Skynet启动流程⼤体如下:
1. 加载配置⽂件
2. 配置⽂件存⼊Lua的全局变量env中
3. 创建和启动C服务的⽇志logger
4. 启动引导模块并开启第⼀个Lua服务(bootstrap)
邓本殷第⼀个启动的Lua服务其实都会由config配置⽂件中的bootstrap配置项所决定,实际项⽬会根据情况进⾏修改,保持使⽤bootstrap作为第⼀个Lua服务,会直接或间接地去启动其他的Lua服务。
1. 配置⽂件
$ vim example/config
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"
Skynet节点启动的必要配置项包括
-- 启动多少个⼯作线程,通常不要超过实际拥有的CPU核⼼数量。
thread = 8
-- 启动的第⼀服务及参数,默认为snlua bootstrap表⽰启动名为bootstrap的Lua服务,即service/bootstrap.lua。
bootstrap = "snlua bootstrap"
-- 使⽤C语⾔编写的服务模块的位置,通常是cservice⽂件下.so⽂件。若系统的动态库不是以.so作为后缀需修改,此路径可配置多项以;分号分隔。
cpath = root.."cservice/?.so"
2. 配置信息结构体
skynet启动时必要的数据被定义在skynet-src/skynet_imp.h⽂件中的skynet_config结构体中。
$ vim syket-src/skynet_imp.h
#ifndef SKYNET_IMP_H
#define SKYNET_IMP_H
//skynet配置信息结构体
struct skynet_config {
//启动⼯作线程数量,建议不要设置超过实际拥有的CPU的核⼼数。 int thread;
//skynet⽹络节点的唯⼀编号,1到255之间的任意整数。⼀个skynet⽹络最多⽀持255个节点。
int harbor;
//是否开启统计功能,统计每个服务使⽤了多少CPU时间,默认为开启。
澳门特别行政区区徽
int profile;
//后台模式:daemon="./skynet.pid"以后台模式启动skynet,同时需配置logger⽇志项中输出的log。
const char * daemon;
//设置使⽤C语⾔编写的服务模块的位置,通常指的是cservice⽬录下的.so⽂件。
const char * module_path;
//设置skynet启动的第⼀个服务以及启动参数,默认配置为snlua bootstrap,即启动⼀个名为bootstrap的Lua服务,通常指的是service/bootstrap.lua⽂件。
const char * bootstrap;
//设置skynet内置skynet_error这个C API将⽇志信息输出⽂件的路径,如果配置为nil将输出到标准输出,可配置⼀个⽂件名将信息保存在特定的⽂件中。
const char * logger;
//⾃定义log服务,默认为logger,可参考service_logger.c来实现。若希望使⽤LUa来实现log服务则填写snlua,并在logger中配置具体的Lua服务的名字。在examp const char * logservice;
};
#define THREAD_WORKER 0
#define THREAD_MAIN 1
#define THREAD_SOCKET 2
#define THREAD_TIMER 3
#define THREAD_MONITOR 4
void skynet_start(struct skynet_config * config);
#endif
3. ⼊⼝函数和初始化
启动Skynet所使⽤的指令./skynet example/config实际上是调⽤ skynet-src/skynet_main.c脚本的⼊⼝函数main,调⽤时将config配置⽂件地
址作为参数传⼊函数中,在主函数中主要完成设置环境和加载配置⽂件两项⼯作。
$ vim skynet-src/skynet_main.c
//配置信息
#include skynet_imp.h
// ⼊⼝主函数
int
main(int argc, char *argv[]) {
//定义保存配置⽂件地址的变量
const char * config_file = NULL ;
//若传⼊配置⽂件地址作为参数
if (argc > 1) {
if (argc > 1) {
//读取配置⽂件的地址并保存到配置⽂件变量中
config_file = argv[1];
} else {
//若没有传⼊配置⽂件地址则提⽰错误并结束程序
fprintf(stderr, "Need a config file. Please read skynet wiki : github/cloudwu/skynet/wiki/Config\n"
"usage: skynet configfilename\n");
return 1;
}
//初始化:todo
luaS_initshr();
//全局初始化,为线程特有数据使⽤pthread_key_create()函数创建⼀个key,然后使⽤pthread_setspecific()函数为这个key设置value值。
skynet_globalinit();
//初始化Lua环境,创建⼀个全局数据结构struct skynet_env *E,并初始化结构的值。
skynet_env_init();
//设置信号处理函数,⽤于忽略sigpipe信号的处理
sigign();
//创建启动skynet所必须的配置信息结构数据
struct skynet_config config;
//申请⼀个Lua虚拟机
struct lua_State *L = luaL_newstate();
//连接到必要的Lua库到上⾯申请的Lua虚拟机中
luaL_openlibs(L); // link lua lib
//执⾏配置⽂件并在Lua中进⾏读取
int err = luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");
assert(err == LUA_OK);
//将C读取的配置⽂件内容串压⼊栈顶
lua_pushstring(L, config_file);
//执⾏栈顶的程序块(chunk),实际是加载配置Lua脚本字符串的内容
err = lua_pcall(L, 1, 1, 0);
战栗者
if (err) {
fprintf(stderr,"%s\n",lua_tostring(L,-1));
lua_close(L);
return 1;
}
//初始化保存配置信息的环境变量env
_init_env(L);
//通过skynet_getenv()接⼝从env中获取配置⽂件的信息,其实内部机制是通过lua_setglobal将之前压⼊栈顶的配置⽂件config_file转换为Lua中的全局变量 config.thread = optint("thread",8);
config.harbor = optint("harbor", 1);
config.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);
leukemia//关闭上⾯创建的Lua虚拟机L
lua_close(L);
//开始执⾏skynet,正式启动skynet服务程序的操作
skynet_start(&config);
//删除线程存储的key,对应skynet_globalinit()
skynet_globalexit();
//初始化结束,对应luaS_initshr()
luaS_exitshr();
return 0;
}
3. 启动skynet服务程序
在skynet-src/skynet_main.c的main函数末尾,也就是完成环境设置和配置加载后,会调⽤skynet_start(&config);。skynet_start函数和是
在skynet-src/skynet_start.c中定义的,作⽤是开始执⾏skynet。