brpc icon indicating copy to clipboard operation
brpc copied to clipboard

brpc是否考虑自身提供无损热升级能力?

Open Huixxi opened this issue 3 years ago • 8 comments

Is your feature request related to a problem? (你需要的功能是否与某个问题有关?) 目前brpc server的无损热升级依赖业务端Pass平台屏蔽BNS实例的方式实现,一般按照一定的并发度来变更实例,变更每个实例的时候,先在BNS屏蔽该实例,等待BNS下发生效,再重启实例完成升级,然后再BNS解屏蔽。这种热升级方式一般情况下可以实现无损的实例升级,但是当下游集群服务器数量很大,服务器QPS很高的情况下则会带来如热升级时间过长,热升级期间会增加其他机器的负载等一系列问题。综上,brpc是否考虑自身提供无损热升级能力。

Describe the solution you'd like (描述你期望的解决方法) brpc server重启升级过程能保证已有连接不断开和请求不丢弃,同时能正常接收新请求。 实现方案 bRPC Server的无损热升级是一种进程级的实现方式:

  1. 发布新的bin文件去覆盖老的bin文件(升级业务代码,编译产生新的bin文件);
  2. 进程监听重启信号,一般使用的是Linux的SIGUSR1或者SIGUSR2系统预留的这两个自定义信号或者使用SIGHUP信号代表重启信号;
  3. 向进程发送重启信号(默认kill -SIGHUP xx_pid),当进程收到重启信号,则以子进程(fork&exec)的方式加载新的bin文件启动;
  4. 子进程启动过程中,父子进程通过一个Unix Domain Socket,以同步的方式无损迁移旧进程的监听文件描述符listenfds和长连接文件描述符connfds;
  5. 新的子进程启动完成后给通知旧的父进程退出,完全接管处理新的连接请求;
  6. 父进程收到通知后优雅退出,至此本次无损热升级流程结束。

关键点:

  1. 如何判断进程是否为子进程;
  2. 子进程如何继承监听文件描述符,接受新请求;
  3. 长连接如何无损迁移;
  4. 父进程的长连接存量响应如何处理;
  5. 父进程如何优雅退出。

热升级场景: bRPC Server的无损热升级是一种协议无关的实现,只要业务使用的是bRPC Server提供的服务,就支持这种无损热升级能力。但热升级本身有两个场景,目前:

  1. 在同一虚拟机或者容器内通过替换服务进程二级制文件的方式来实现无损热升级(主要场景,支持✅)。
  2. 虚拟机或容器层面的热升级,直接在重新拉起的另一台虚拟机或容器中重启服务实现无损热升级(非主要场景,暂不支持❌)。

Describe alternatives you've considered (描述你想到的折衷方案)

Additional context/screenshots (更多上下文/截图)

Huixxi avatar Jan 05 '22 06:01 Huixxi

类似 nginx 的reload方式?

JiaoZiLang avatar Jan 06 '22 02:01 JiaoZiLang

嗯嗯,类似nginx 的reload方式,还有Envoy的那种hot restart方式。

Huixxi avatar Jan 06 '22 04:01 Huixxi

嗯嗯,类似nginx 的reload方式,还有Envoy的那种hot restart方式。

简单暴力一些,上游服务加重试呗

JiaoZiLang avatar Jan 06 '22 06:01 JiaoZiLang

嗯嗯,类似nginx 的reload方式,还有Envoy的那种hot restart方式。

简单暴力一些,上游服务加重试呗

有损哇

Huixxi avatar Jan 06 '22 07:01 Huixxi

类似 nginx 的reload方式?

和reload还不太一样,reload只是热重启,运行的bin文件还是老的bin文件;热升级是新bin文件替换旧的bin文件。

Huixxi avatar Jan 09 '22 07:01 Huixxi

类似 nginx 的reload方式?

和reload还不太一样,reload只是热重启,运行的bin文件还是老的bin文件;热升级是新bin文件替换旧的bin文件。 😄

JiaoZiLang avatar Jan 09 '22 08:01 JiaoZiLang

或者直接把业务代码写到 .so 里面,然后进程根据信号重新 dlopen 这些 .so

uuuuu-diwu avatar Apr 24 '22 03:04 uuuuu-diwu

或者直接把业务代码写到 .so 里面,然后进程根据信号重新 dlopen 这些 .so

不建议这么搞,这样可能会有很多坑,dlopen只是重新加载so中的符号 ,但是对于so中的代码所申请的资源(如内存、fd、线程)是不保证释放的,需要业务代码非常谨慎地处理。而且为了保证升级过程请求平滑处理,会有一段时间新老so并存,这可能会产生符号冲突之类的问题

wwbmmm avatar Apr 24 '22 06:04 wwbmmm