不停服更新二进制文件

原文

http://www.zhaoch.top/操作系统/linux/不停服更新二进制文件.html

不停服更新二进制文件

www.zhaoch.top > 操作系统 > linux

虽然目前分布式架构和keepalived等工具的存在,对于某些特殊的程序,仍然需要不停服更新二进制文件。 这里参考nginx的实现介绍下如何实现这个功能的

痛点

  • 已有的链接不中断,直至这个客户端完成业务处理
  • 使用新的程序文件处理新的请求
  • 新老进程同时存在还要监听相同的端口

思路

  • 因为要监听相同端口所以一般都是父子进程
  • 常用的fork不能更新二进制文件,需要再通过exec重新加载文件
  • 监听相同端口可以通过把句柄作为参数或者环境变量传递给exec族函数继续使用

参考ngx_exec_new_binary

过程

  • 更新可执行程序
  • 向主进程发送信号(例如:USR2),立即设置全局变量
  • 事件处理循环中老进程检查到全局变量后,不再accept新的连接,已有的连接正常处理
  • fork一个子进程,子进程通过exec族函数更新二进制,将listen的句柄通过参数或者环境变量
  • 子进程开始accept,新接入的连接由新程序处理
  • 老程序持续运行,直至所有的连接都完成业务(可设置超时时间),退出
  • 此时只有子程序在运行

示例代码

编辑app_new.cpp 与 app_old.cpp两个文件,app_old.cpp内容如下

#include <stdlib.h> #include <iostream>  #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h>   using namespace std; extern char **environ;  // difference form old and new in binary file const char *TITLE = "APP-OLD ";  bool g_update = false; bool g_stop = false;  void signal_handler(int sig) {     cout << "signal_handler" << sig << endl;     if (sig == SIGUSR2) {         g_update = true;     }     g_stop = true; }  void update_binary(char* argv[], int fd) {     if (fork() != 0) {         return;     }      char *fdstr = new char[100];     snprintf(fdstr, 100, "FD=%d", fd);      int n;     for (n = 0; environ[n]; n++);      // copy environ     char **env = new char*[n + 1];     for (int i = 0; i < n - 1; i++) {         env[i] = environ[i];     }      // app fd into environ     env[n - 1] = fdstr;     env[n] = NULL;      // importent exec app_new     execvpe("./app_new", argv, env); }  int main(int argc, char* argv[]) {     int fd = -1;     g_stop = false;     g_update = false;      cout << TITLE << getpid() << endl;      char *oldfd = getenv("FD");      if (oldfd) {         fd = atoi(oldfd);      } else {         struct sockaddr_in addr;         addr.sin_family = AF_INET;         addr.sin_port = htons(9999);         addr.sin_addr.s_addr = inet_addr("127.0.0.1");          fd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);         if (fd < 0) {             return 1;         }         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || listen(fd, 4096) < 0) {             close(fd);             return 1;         }          if (signal(SIGUSR2, signal_handler) == SIG_ERR             || signal(SIGTERM, signal_handler) == SIG_ERR             || signal(SIGINT, signal_handler) == SIG_ERR) {              close(fd);             return 1;         }     }      while (!g_stop) {         cout << TITLE << getpid() << " fd=" << fd << endl;         sleep(1);     }      if (g_update) {         update_binary(argv, fd);     }      // semulate waiting for the all connection diedown     for (int i = 0; i < 10; i++) {         cout << TITLE << getpid() << " fd=" << fd << endl;         sleep(1);     }      cout << TITLE << "end" << endl;      return 0; } 

app_new.cpp仅仅TITLE取名不同,用于区分新旧二进制文件

diff app_old.cpp app_new.cpp  < const char *TITLE = "APP-OLD "; --- > const char *TITLE = "APP-NEW "; 

编译两个文件用于对比测试

g++ app_old.cpp -o app_old g++ app_new.cpp -o app_new 

执行结果

./app_old APP-OLD 8521 APP-OLD 8521 fd=3 APP-OLD 8521 fd=3 APP-OLD 8521 fd=3 signal_handler12  <- 执行命令 kill -USR2 8521 APP-OLD 8521 fd=3 <- 新旧并行 APP-NEW 8524 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD 8521 fd=3 APP-NEW 8524 fd=3 APP-OLD end          <- 旧进程退出,只剩新进程 APP-NEW 8524 fd=3 APP-NEW 8524 fd=3 APP-NEW 8524 fd=3 APP-NEW 8524 fd=3 APP-NEW 8524 fd=3 APP-NEW 8524 fd=3 

The End

原文地址:https://www.cnblogs.com/GhostZCH/p/9637106.html

时间: 2024-10-11 18:21:56

不停服更新二进制文件的相关文章

JAVA代码热部署,在线不停服动态更新

本地debug的时候,可以实时编译并更新代码,线上也可以不停服来动态更新类,即所说的java热部署. JDK代理的两种方式: 1.premain方式是Java SE5开始就提供的代理方式,但其必须在命令行指定代理jar,并且代理类必须在main方法前启动,它要求开发者在应用启动前就必须确认代理的处理逻辑和参数内容等等 2.agentmain方式是JavaSE6开始提供,它可以在应用程序的VM启动后再动态添加代理的方式 agentmain应用场景: 比如正常的生产环境下,一般不会开启代理功能,但是

跨园区容灾,升级不停服——高可用负载均衡集群实践

对于云计算行业来说,云服务的可用性和可扩展性是的检测其服务质量的重要标准,也是最受用户关注的两大难题.各云计算厂商针对容灾.升级等需求的解决方案,最能够体现其底层架构的实力.腾讯云基于基础架构的优势,为分期乐.微信红包等平台提供技术支持,可以完美满足如下三点需求: 1. 高可用能力,容灾能力强,升级不停服 2. 可扩展性强,功能丰富,性能超高 3. 避免重复造轮子,性价比之王 近期,针对一些客户对腾讯云产品可用性的问询,腾讯云基础产品团队对负载均衡产品的原理做出详细阐述,并希望通过对腾讯负载均衡

python+django开发的运维工具——游戏内测服更新系统

这套系统,是学了python和django来,第一个正式开发好的小项目.小工具,只不过是,这套系统,需要优化的东西还很多,但目前也用的OK.年后回来,准备把新吸收的技术,开发正式服更新系统. 在这里,先感谢下老男孩运维培训机构,我的linux运维和python运维开发是从这里起步的,现在又准备报名他的mysql dba课程了.另外得感谢下刘天斯大神哈,从他出版的<Python自动化运维:技术与最佳实践>书上学了不少东西,并加入到了这个小工具中. 不啰嗦了,先工具图吧(以下图都截自我测试服上的,

跨园区容灾,升级不停服:高可用负载均衡集群实践

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云中间件团队发表于云+技术周刊特别版 作者:方坤丁 对于云计算行业来说,云服务的可用性和可扩展性是的检测其服务质量的重要标准,也是最受用户关注的两大难题.各云计算厂商针对容灾.升级等需求的解决方案,最能够体现其底层架构的实力.腾讯云基于基础架构的优势,为分期乐.微信红包等平台提供技术支持,可以完美满足如下三点需求: 1. 高可用能力,容灾能力强,升级不停服 2. 可扩展性强,功能丰富,性能超高 3. 避免重复造轮子,性价比之王

springboot 不停服动态更新定时任务时间(转)

转 https://blog.csdn.net/u012129558/article/details/80834303 Spring框架自3.0版本起,自带了任务调度功能,好比是一个轻量级的Quartz,而且使用起来也方便.简单,且不需要依赖其他的JAR包.秉承着Spring的一贯风格,Spring任务调度的实现同时支持注解配置和XML配置两种方式. 再来谈谈变态的项目需求:我们正在做一个智能数字电表的数据采集项目,项目最终会在多个工业园上线,每个工业园对电表数据的采集周期可以进行自定义,例如A

nginx重新加载配置(不停服)

RT,改变配置想让它生效而不停止服务,如下两种方式都可以: 1) nginx -t;  nginx -s reload2) nginx -t;  kill -HUP <nginx_master_process_pid> nginx -t 检查nginx配置的语法,操作前都要检查一下,很重要,发现错误可及时修正. 停止操作停止操作是通过向nginx进程发送信号(什么是信号请参阅linux文 章)来进行的步骤1:查询nginx主进程号ps -ef | grep nginx在进程列表里 面找mast

mysql合服 更新相同的用户名前追加服务器编号

表结构: 1 CREATE TABLE IF NOT EXISTS `user` ( 2 `user_id` int(11) NOT NULL COMMENT '主键', 3 `user_level` int(11) NOT NULL DEFAULT 0 COMMENT '等级', 4 `user_name` varchar(32) NOT NULL DEFAULT 0 COMMENT '名称', 5 `server_id` int(11) NOT NULL DEFAULT 0 COMMIT '

nginx重新编译不停服

找到安装nginx的源码根目录,如果没有就下载新的安装包 tar xvzf nginx-1.3.2.tar.gz 查看ngixn版本极其编译参数 /usr/local/nginx/sbin/nginx -V 进入nginx源码目录 cd nginx-1.3.2 以下是重新编译的代码和模块 ./configure --prefix=/usr/local/nginx--with-http_stub_status_module --with-http_ssl_module --with-file-ai

博客更换至 www.zhaoch.top

博客更换至 www.zhaoch.top 随手拷了一些链接 http://www.zhaoch.top/操作系统/linux/不停服更新二进制文件.html http://www.zhaoch.top/编程/go/ping-pong测试备忘.html http://www.zhaoch.top/编程/c_cpp/共享内存.html http://www.zhaoch.top/编程/c_cpp/可变参数的使用.html http://www.zhaoch.top/操作系统/linux/常用命令备忘