码云基础服务工具包
在开发服务程序时,我们通常需要支持解析用户参数,以 daemon 的方式运行,还有支持日志,
对于一些特定的场景,我们还要支持自动重启,异常退出追踪。不同的服务都需要实现一套,
非常麻烦,而 wink 库则是解决这一问题。
命令行模板
wink::ProcessArgvTemplate 类是命令行模板类,当用户使用时,需要实现以下几个函数:
usage 打印用户帮助信息并退出,-? -h --help 命令行参数开启。
version 打印版本信息并退出,-v --version ,当参数中含有 --quiet(-q) 不打印详细版本信息。
appinitialize 传入标记的配置文件路径(可能是 null),用户需要自己规划和解析。
daemonizetask -s (--signal) 用户自定义。
daemonize -D (--daemon) daemon 实现代码。
当输入参数 -d (--debug) 时,标记为 DebugModel ,用户可以根据自己需要,自行设置。
namespace wink {
void ProcessArgvTemplate::usage() {
fprintf(stderr, "hello argv_example usage\n");
}
void ProcessArgvTemplate::version(bool quiet) {
if (quiet) {
fprintf(stderr, "1.0\n");
} else {
fprintf(stderr, "argv_example 1.0\n");
}
}
bool ProcessArgvTemplate::appinitialize(const char* file) {
if (file)
fprintf(stderr, "config file: %s\n", file);
else
fprintf(stderr, "Please search your default config\n");
fprintf(stderr, "saved_ value your can do it some thing\n");
return true;
}
int ProcessArgvTemplate::daemonizetask(const char* sig) {
fprintf(stderr, "-s %s\n", sig);
return 0;
}
bool ProcessArgvTemplate::daemonize() {
/// start a process as a daemon
return true;
}
}
文件系统简单抽象
在开发服务器程序时,需要支持默认配置,对于配置文件我们优先选择用户使用 -c (--config) 指定的
配置文件,而后是当前目录的配置文件,最后是安装目录的配置 config 目录下的配置文件,如果利用
nginx 一样的机制,即在编译时就设置好 PREFIX ,这样导致无法平滑的移动到不同机器不同目录,
所以我们利用 可执行程序自身目录来解析配置文件,对于 OSX FreeBSD Linux, 获取可执行程序的自身路径不尽相同,所以我们写了抽象函数来支持这些。在 dotnet/coreclr 中有 GetEntrypointExecutableAbsolutePath ,我们将其移植过来,并加以整合。
当然还有一些其他的文件系统函数。可以查看 fs.hpp
守护进程和函数栈追踪
wink 支持守护进程,分别支持守护进程的创建,停止和重启,daemon 退出调用函数,改变进程标题(也就是修改 ps 显示,在 Linux 系统下是 /proc/$PID/cmdline),设置函数栈追踪(在遇到 SIGSEGV,SIGABRT 信号时打印函数栈),函数声明如下
#include
#include
#include
#include
namespace wink {
using DaemonizeCall = std::function;
namespace Signal {
enum DeamonizeSignal {
Exit = SIGUSR1, ///
Graceful = SIGUSR2 ///
};
}
bool initialize(const std::string &name, const std::string &pidfile,
std::size_t slaves, const DaemonizeCall &call = {});
#if defined(__linux__) || defined(__CYGWIN__)
void initializetitle(int argc, char** argv);
#else
inline void initializetitle(int argc, char** argv) {}
#endif
bool changetitle(const char *title);
bool symbolize();
bool restart(const std::string &name, const std::string &pidfile,
bool force = true);
bool stop(const std::string &name, const std::string &pidfile);
}; // namespace daemonize
更多的细节可以查看代码。
平滑重启
当支持 -s restart 参数将支持平滑重启,强制重启为 -s restart -f,当然在调用 daemonize::restart 函数时,可以显式的设置,也可以使用 isforced 变量支持,此变量为 ProcessArgvTemplate 的成员变量。为支持异步信号安全,如 asio 程序需要使用 signal_set 实现平滑重启在 work process 进程中的处理,否则程序会自动退出。
平滑重启意味着子进程接受到信号后并不会退出,而是关闭监听套接字,然后等待所有请求处理完毕,因此可能因为其他原因,进程无法正常的结束,一直存活,虽然不会影响到新的进程工作,但是还是需要处理。
wink 给旧的进程设置了定时器,当定时器超时后,将会结束就进程,默认情况下定时器超时为 480s,用户完全可以使用如下操作修改定时器参数。
add_compile_options("-DGRACEFUL_DELAYTIME=120")
Wink 守护进程
wink 支持崩溃自动重启,通常来说,崩溃自动重启次数为 200, 但用户可以设置 WINK_CRASH_LIMIT 环境变量去减小或者加大 Wink 的崩溃自动重启限制。
移植
POSIX 系统(FreeBSD,MacOS,NetBSD,Linux)可以在 *.unix.cc 中实现其代码,如果移植到 Windows 可以添加 *.win32.cc
第三方组件
wink 使用了一些第三方组件,下表中有列出:
License
Wink 使用 MIT License. 一些第三方源文件请查看 Other Licenses