炒虾仁,五脏,1g等于多少mb-大坑视线-专注闭坑-重新发现价值

频道:趣闻中心 日期: 浏览:117

从问题开端

先来抛一块砖,关于静态编译的应用程序,比方用C、C++、Golang或许其它的言语编写的程序,假设咱们修正一个BUG或许添加一个新的特性后,如安在服务不下线的情况下更远应用程序呢?

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



假设你被苹果砸中了怎样办?

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



那么咱们回到方才这个问题 :

当咱们修正BUG,添加新的需求后,怎样如丝般顺滑地晋级服务器应用程序,而不会中止服务?

这个问题意味着:

C / C++ / GO都是静态言语,一切的指令都编译在可履行文件,晋级就意味着编译新的履行文件替换旧的履行文件,现已运转的进程怎样加载新的image(可履行程序文件)去履行呢?

正在处理的事务逻辑不能中止,正在处理的衔接不能暴力中止?

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

用个形象上的比方表明便是:

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

然后,有个轮胎,爆了

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

哦,Lee哥,我理解了,在这些情况下,咱们是不能运用哪个全能地“重启”去处理问题的。

第一种处理计划:灰度发布和A/B测验引起的考虑

灰度发布(又叫金丝雀发布)是指在黑与白之间,能够滑润过渡的一种发布办法。在其上能够进行A/B testing,即让一部分用户持续用产品特性A,一部分用户开端用产品特性B,假设用户对B没有什么对立定见,那么逐渐扩大范围,把一切用户都迁移到B 上面来。灰度发布能够确保全体体系的安稳,在初始灰度的时分就能够发现、调整问题,以确保其影响度。使用nginx做灰度发布的计划如下图:



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怎样去如丝般晋级服务程序呢?



比方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 =3down;
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进程担任用户的恳求处理。



如上一个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恳求和长衔接怎样处理?



怎样发动新的的image:



好了,以上便是zero down-time update的一些计划,假设还有不理解能够看下面这个视频。

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