此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善
项目地址:https://gitee.com/lzhiqiang1999/server-framework
简介
项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。
详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。
守护进程
1. 主要功能
- 将进程与终端解绑,转到后台运行
- 实现了双进程唤醒功能,由父进程作为守护进程,当子进程异常结束,父进程在指定时间重新创建子进程
2. 功能演示
- 在子进程放一个定时器,每秒打印一次。
int server_main(int argc, char** argv) {
LOG_INFO(g_logger) << johnsonli::ProcessInfoMgr::GetInstance()->toString();
johnsonli::IOManager iom(1);
iom.addTimer(1000, [](){
LOG_INFO(g_logger) << "onTimer";
static int count = 0;
if(++count > 10) {
exit(1);
}
}, true);
return 0;
}
int main(int argc, char** argv) {
return johnsonli::start_daemon(argc, argv, server_main, argc != 1);
}
3. 模块介绍
3.1 ProcessInfo
- 记录父子进程的信息
struct ProcessInfo {
/// 父进程id
pid_t parent_id = 0;
/// 主进程id
pid_t main_id = 0;
/// 父进程启动时间
uint64_t parent_start_time = 0;
/// 主进程启动时间
uint64_t main_start_time = 0;
/// 主进程重启的次数
uint32_t restart_count = 0;
std::string toString() const;
};
3.2 守护进程
- 主要有三个方法
start_deamon
、real_start
、real_daemon
star_deamon
是入口,其中注册一个回调函数,负责逻辑处理。如果不使用守护进程,就直接调用real_start
,否则调用real_deamon
int start_daemon(int argc, char** argv
, std::function<int(int argc, char** argv)> main_cb
, bool is_daemon)
{
if(!is_daemon) {
ProcessInfoMgr::GetInstance()->parent_id = getpid();
ProcessInfoMgr::GetInstance()->parent_start_time = time(0);
return real_start(argc, argv, main_cb);
}
return real_daemon(argc, argv, main_cb);
}
real_start
,真正调用回调函数的地方
static int real_start(int argc, char** argv,
std::function<int(int argc, char** argv)> main_cb) {
ProcessInfoMgr::GetInstance()->main_id = getpid();
ProcessInfoMgr::GetInstance()->main_start_time = time(0);
return main_cb(argc, argv);
}
real_deamon
,使用守护进程,在后台执行,当子进程异常退出时,父进程会重新创建子进程,继续逻辑处理。
static int real_daemon(int argc, char** argv,
std::function<int(int argc, char** argv)> main_cb)
{
daemon(1, 0);
ProcessInfoMgr::GetInstance()->parent_id = getpid();
ProcessInfoMgr::GetInstance()->parent_start_time = time(0);
while(true)
{
pid_t pid = fork();
if(pid == 0) // 子进程
{
//子进程返回
ProcessInfoMgr::GetInstance()->main_id = getpid();
ProcessInfoMgr::GetInstance()->main_start_time = time(0);
LOG_INFO(g_logger) << "process start pid=" << getpid();
return real_start(argc, argv, main_cb);
}
else if(pid < 0) // 出错
{
LOG_ERROR(g_logger) << "fork fail return=" << pid
<< " errno=" << errno << " errstr=" << strerror(errno);
return -1;
}
else // 父进程
{
//父进程返回
int status = 0;
waitpid(pid, &status, 0);
// 有退出状态,异常终止
if(status)
{
if(status == 9)
{
LOG_INFO(g_logger) << "killed";
break;
}
else
{
LOG_ERROR(g_logger) << "child crash pid=" << pid
<< " status=" << status;
}
}
else
{
LOG_INFO(g_logger) << "child finished pid=" << pid;
break;
}
// 异常终止需要再开一次子进程
ProcessInfoMgr::GetInstance()->restart_count += 1;
sleep(g_daemon_restart_interval->getValue());
}
}
return 0;
}