热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

zerodowntimeupdate服务的方案

从问题开始先来抛一块砖,对于静态编译的应用程序,比如用C、C、Golang或者其它的语言编写的程序,如果我们修改一个BUG或者添加一个新的

从问题开始 

先来抛一块砖,对于静态编译的应用程序,比如用C、C++、Golang或者其它的语言编写的程序,如果我们修改一个BUG或者添加一个新的特性后,如何在服务不下线的情况下更远应用程序呢?

抛出了一个问题,一个很平常的问题,有人对问题思考比较透彻,比如牛顿,被苹果砸中了之后,引起了很多的思考,最后发现了万有引力定律。

640?wx_fmt=png

玩笑话一句,那我们如果被苹果砸中了会不死变成智障呢?

640?wx_fmt=jpeg

那么我们回到刚才这个问题 :

当我们修复BUG,添加新的需求后,如何如丝般顺滑地升级服务器应用程序,而不会中断服务?

这个问题意味着:

  1. C / C++ / GO都是静态语言,所有的指令都编译在可执行文件,升级就意味着编译新的执行文件替换旧的执行文件,已经运行的进程如何加载新的image(可执行程序文件)去执行呢?

  2. 正在处理的业务逻辑不能中断,正在处理的连接不能暴力中断?

这种如丝般顺滑地升级应用程序,我们称之为热更新。

用个形象上的比喻表示就是:

你现在在坐卡车,卡车开到了150KM/H

然后,有个轮胎,爆了

然后,司机说,你就直接换吧,我不停车。你小心点换

哦,Lee哥,我明白了,在这些情况下,我们是不能使用哪个万能地“重启”去解决问题的。

第一种解决方案:灰度发布和A/B测试引起的思考 

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B 上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。利用nginx做灰度发布的方案如下图:

640?wx_fmt=png

nginx是一个反向代理软件,可以把外网的请求转发到内网的业务服务器上,系统的分层的设计,一般我们把nginx归为接入层,当然LVS/F5/Apache等等都能去转发用户请求。比如我们来看一个nginx的配置:

http {

    upstream cluster {

        ip_hash;

        server 192.168.2.128:8086 weight=1 fail_timeout=15 max_fails =3;

        server 192.168.2.130:8086 weight=2 fail_timeout=15 max_fails =3;

    }

    server {

        listen 8080;

        location / {

            proxy_pass http://cluster;

        }

    }

}

我们对8080端口的访问,都会转发到cluster说定义的upstream里,upstream里会根据IP hash的策略转发给192.168.2.128和192.168.2.130的8086端口的服务上。这里配置的是ip hash,当然nginx还支持其他策略。

那么通过nginx如何去如丝般升级服务程序呢?

640?wx_fmt=png

比如nginx的配置:

http {  

    upstream cluster {  

        ip_hash;

        server 192.168.2.128:8086 weight=1 fail_timeout=15 max_fails =3;

        server 192.168.2.130:8086 weight=2 fail_timeout=15 max_fails =3;

    }  

   

    server {  

        listen 80;  

  

        location / {

            proxy_pass http://cluster;  

        }  

    }  

}

假如我们的服务部署在192.168.2.128上,现在我们修复BUG或者增加新的特性后,我们重新部署了一台服务(比如192.168.2.130上),那么我们就可以修改nginx配置如上,然后执行nginx -s reload加载新的配置,这样我们现有的连接和服务都没有断掉,但是新的业务服务已经可以开始服务了,这就是通过nginx做的灰度发布,依据这样的方法做的测试称之为A/B测试,好了,那如何让老的服务彻底停掉呢?

可以修改nginx的配置如下,即在对应的upstream的服务器上添加down字段:

http {  

    upstream cluster {  

        ip_hash;

        server 192.168.2.128:8086 weight=1 fail_timeout=15 max_fails =3 down;

        server 192.168.2.130:8086 weight=2 fail_timeout=15 max_fails =3;

    }  

   

    server {  

        listen 80;  

  

        location / {

            proxy_pass http://cluster;  

        }  

    }  

}

这样等过一段时间,就可以把192.168.2.128上的服务给停掉了。

这就是通过接入层nginx的一个如丝般顺滑的一个方案,这种思想同样可以应用于其他的比如LVS、apache等,当然还可以通过DNS,zookeeper,etcd等,就是把流量全都打到新的系统上去。

灰度发布解决的流量转发到新的系统中去,但是如果对于nginx这样的应用程序,或者我就是要在这台机器上升级image,那怎么办呢?这就必须要实现热更新,这里需要考虑的问题是旧的服务如果缓存了数据怎么办?如果正在处理业务逻辑怎么办?

第二种解决方案:nginx的热更新方案 

nginx采用Master/Worker的多进程模型,Master进程负责整个nginx进程的管理,比如停机、日志重启和热更新等等,worker进程负责用户的请求处理。

640?wx_fmt=png

如上一个nginx里配置的所有的监听端口都是首先在Master进程里create的socket(sfd)、bind、listen,然后Master在创建worker进程的时候把这些socket通过unix domain socket复制给了Worker进程,Worker进程把这些socket全都添加到epoll,之后如果有客户端连接进来了,则由worker进程负责处理,那么也就是说用户的请求是由worker进程处理的。

先交代了nginx的IO处理模型的背景,然后我们再看nginx的热更新方案:

升级的步骤:

第一步:升级nginx二进制文件,需要先将新的nginx可执行文件替换原有旧的nginx文件,然后给nginx master进程发送USR2信号,告知其开始升级可执行文件;nginx master进程会将老的pid文件增加.oldbin后缀,然后调用exec函数拉起新的master和worker进程,并写入新的master进程的pid

UID        PID  PPID  C STIME TTY          TIME CMD

root      4584     1  0 Oct17 ?        00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx

root     12936  4584  0 Oct26 ?        00:03:24 nginx: worker process

root     12937  4584  0 Oct26 ?        00:00:04 nginx: worker process

root     12938  4584  0 Oct26 ?        00:00:04 nginx: worker process

root     23692  4584  0 21:28 ?        00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx

root     23693 23692  3 21:28 ?        00:00:00 nginx: worker process

root     23694 23692  3 21:28 ?        00:00:00 nginx: worker process

root     23695 23692  3 21:28 ?        00:00:00 nginx: worker process

关于exec家族的函数说明见下:

NAME

       execl, execlp, execle, execv, execvp, execvpe - execute a file

SYNOPSIS

       #include

       extern char **environ;

       int execl(const char *path, const char *arg, ...

                       /* (char  *) NULL */);

       int execlp(const char *file, const char *arg, ...

                       /* (char  *) NULL */);

       int execle(const char *path, const char *arg, ...

                       /*, (char *) NULL, char * const envp[] */);

       int execv(const char *path, char *const argv[]);

       int execvp(const char *file, char *const argv[]);

       int execvpe(const char *file, char *const argv[],

                       char *const envp[]);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       execvpe(): _GNU_SOURCE

DESCRIPTION

       The  exec()  family of functions replaces the current process image with a new process image.  The functions described in this manual page are front-ends for execve(2).

       (See the manual page for execve(2) for further details about the replacement of the current process image.)

       The initial argument for these functions is the name of a file that is to be executed.

       The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn.  Together they describe a  list

       of  one or more pointers to null-terminated strings that represent the argument list available to the executed program.  The first argument, by convention, should point

       to the filename associated with the file being executed.  The list of arguments must be terminated by a null pointer, and, since  these  are  variadic  functions,  this

       pointer must be cast (char *) NULL.

       The  execv(),  execvp(),  and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program.

       The first argument, by convention, should point to the filename associated with the file being executed.  The array of pointers must be terminated by a null pointer.

       The execle() and execvpe() functions allow the caller to specify the environment of the executed program via the argument envp.  The envp argument is an array of point‐

       ers  to null-terminated strings and must be terminated by a null pointer.  The other functions take the environment for the new process image from the external variable

       environ in the calling process.


第二步:在此之后,所有工作进程(包括旧进程和新进程)将会继续接受请求。这时候,需要发送WINCH信号给nginx master进程,master进程将会向worker进程发送消息,告知其需要进行graceful shutdown,worker进程会在连接处理完之后进行退出。

UID        PID  PPID  C STIME TTY          TIME CMD

root      4584     1  0 Oct17 ?        00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx

root     12936  4584  0 Oct26 ?        00:03:24 nginx: worker process

root     12937  4584  0 Oct26 ?        00:00:04 nginx: worker process

root     12938  4584  0 Oct26 ?        00:00:04 nginx: worker process

root     23692  4584  0 21:28 ?        00:00:00 nginx: master process /usr/local/apigw/apigw_nginx/nginx

如果旧的worker进程还需要处理连接,则worker进程不会立即退出,需要待消息处理完后再退出。

第三步:经过一段时间之后,将会只会有新的worker进程处理新的连接。

注意,旧master进程并不会关闭它的listen socket;因为如果出问题后,需要回滚,master进程需要法重新启动它的worker进程。

第四步:如果升级成功,则可以向旧master进程发送QUIT信号,停止老的master进程;如果新的master进程(意外)退出,那么旧master进程将会去掉自己的pid文件的.oldbin后缀。

几个核心的步骤和命令说明如下:

  • 操作的命令

master进程相关信号

USR2 升级可执行文件

WINCH 优雅停止worker进程

QUIT 优雅停止master进程

worker进程相关信号

TERM, INT 快速退出进程

QUIT 优雅停止进程

  • nginx本身是一个代理组件(代理http TCP UDP),本身并没有什么业务逻辑,也即没有什么状态数据可言,即使有业务逻辑这套方案也是可以的。

  • nginx是如何graceful shutdown的?也即正在处理的http请求和长连接怎么处理?

640?wx_fmt=png

如何启动新的的image:

640?wx_fmt=png

好了,以上就是zero down-time update的一些方案,如果还有不明白可以看下面这个视频。

https://www.bilibili.com/video/av57429199



推荐阅读
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • Keepalived 提供了多种强大且灵活的后端健康检查机制,包括 HTTP_GET、SSL_GET、TCP_CHECK、SMTP_CHECK 和 MISC_CHECK 等多种检测方法。这些健康检查功能确保了高可用性环境中的服务稳定性和可靠性。通过合理配置这些检查方式,可以有效监测后端服务器的状态,及时发现并处理故障,从而提高系统的整体性能和可用性。 ... [详细]
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • 负载均衡基础概念与技术解析
    随着互联网应用的不断扩展,用户流量激增,业务复杂度显著提升,单一服务器已难以应对日益增长的负载需求。负载均衡技术应运而生,通过将请求合理分配到多个服务器,有效提高系统的可用性和响应速度。本文将深入探讨负载均衡的基本概念和技术原理,分析其在现代互联网架构中的重要性及应用场景。 ... [详细]
  • MySQL性能优化与调参指南【数据库管理】
    本文详细探讨了MySQL数据库的性能优化与参数调整技巧,旨在帮助数据库管理员和开发人员提升系统的运行效率。内容涵盖索引优化、查询优化、配置参数调整等方面,结合实际案例进行深入分析,提供实用的操作建议。此外,还介绍了常见的性能监控工具和方法,助力读者全面掌握MySQL性能优化的核心技能。 ... [详细]
  • 一、Tomcat安装后本身提供了一个server,端口配置默认是8080,对应目录为:..\Tomcat8.0\webapps二、Tomcat8.0配置多个端口,其实也就是给T ... [详细]
  • 2022年2月 微信小程序 app.json 配置详解:启用调试模式
    本文将详细介绍如何在微信小程序的 app.json 文件中启用调试模式(debug),并通过实际案例展示其配置方法和应用场景。 ... [详细]
  • 基于Linux开源VOIP系统LinPhone[四]
    ****************************************************************************************** ... [详细]
  • Flowable 流程图路径与节点展示:已执行节点高亮红色标记,增强可视化效果
    在Flowable流程图中,通常仅显示当前节点,而路径则需自行获取。特别是在多次驳回的情况下,节点可能会出现混乱。本文重点探讨了如何准确地展示流程图效果,包括已结束的流程和正在执行的流程。具体实现方法包括生成带有高亮红色标记的图片,以增强可视化效果,确保用户能够清晰地了解每个节点的状态。 ... [详细]
  • 在分析和解决 Keepalived VIP 漂移故障的过程中,我们发现主备节点配置如下:主节点 IP 为 172.16.30.31,备份节点 IP 为 172.16.30.32,虚拟 IP 为 172.16.30.10。故障表现为监控系统显示 Keepalived 主节点状态异常,导致 VIP 漂移到备份节点。通过详细检查配置文件和日志,我们发现主节点上的 Keepalived 进程未能正常运行,最终通过优化配置和重启服务解决了该问题。此外,我们还增加了健康检查机制,以提高系统的稳定性和可靠性。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
  • 在使用 SQL Server 时,连接故障是用户最常见的问题之一。通常,连接 SQL Server 的方法有两种:一种是通过 SQL Server 自带的客户端工具,例如 SQL Server Management Studio;另一种是通过第三方应用程序或开发工具进行连接。本文将详细分析导致连接故障的常见原因,并提供相应的解决策略,帮助用户有效排除连接问题。 ... [详细]
  • 本文探讨了 Kafka 集群的高效部署与优化策略。首先介绍了 Kafka 的下载与安装步骤,包括从官方网站获取最新版本的压缩包并进行解压。随后详细讨论了集群配置的最佳实践,涵盖节点选择、网络优化和性能调优等方面,旨在提升系统的稳定性和处理能力。此外,还提供了常见的故障排查方法和监控方案,帮助运维人员更好地管理和维护 Kafka 集群。 ... [详细]
  • Linux入门教程第七课:基础命令与操作详解
    在本课程中,我们将深入探讨 Linux 系统中的基础命令与操作,重点讲解网络配置的相关知识。首先,我们会介绍 IP 地址的概念及其在网络协议中的作用,特别是 IPv4(Internet Protocol Version 4)的具体应用和配置方法。通过实际操作和示例,帮助初学者更好地理解和掌握这些基本技能。 ... [详细]
author-avatar
手机用户2502907707
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有