当前位置: 首页 > 后端技术 > Java

发布稳定性-GracefulOffline

时间:2023-04-02 00:09:43 Java

背景介绍最近我负责的项目已经达到100000QPS大关。如此高的QPS,对系统的稳定性要求更高。QPS小的时候,系统更新部署很简单,现在不行了。一部署上游应用端就会来找你的应用怎么了,怎么突然抖的这么厉害。..所以我准备写一篇关于发布稳定性的经验,今天说说优雅的离线。为什么需要GracefulOffline对于在线应用,尤其是高并发应用,在服务更新部署过程中,即从应用停止到重启恢复服务,保证客户端不感知是开发者必须解决的问题阶段。正常的业务请求不会受到影响。传统的解决方案是手动提取流量、停止应用、更新和重启服务,但手动操作过于繁琐,不适合大型系统。因此,服务需要一种自动化的机制来自动抽取流量,并保证已经到达的请求得到处理,这就是优雅的离线。适用场景JVM主动关闭(System.exit(int))。应用收到SIGTERM或SIGINT信号,优雅离线退出Dubbo服务。Dubbo服务优雅下线默认开启,停机等待时间为10秒#Dubbo优雅下线等待时间,默认10秒,这里配置20秒dubbo.service.shutdown.wait=20000下线步骤服务端和客户端的实现如图:实现原理查看Dubbo源码查看下线过程1.服务启动时加载类org.apache.dubbo.config.AbstractConfig会调用DubboShutdownHook.getDubboShutdownHook()。register()来注册ShutdownHook钩子/***注册ShutdownHook*/publicvoidregister(){if(!registered.get()&®istered.compareAndSet(false,true)){Runtime.getRuntime().addShutdownHook(getDubboShutdownHook());}}2。每个ShutdownHook都是一个独立的线程,当收到关闭应用的kill信号量时,会触发DubboShutdownHook执行run方法,然后执行doDestroy方法销毁所有注册的服务和协议。@Overridepublicvoidrun(){if(logger.isInfoEnabled()){logger.info("现在运行关闭钩子。");}doDestroy();}/***销毁所有资源,包括注册表和协议。*/publicvoiddoDestroy(){if(!destroyed.compareAndSet(false,true)){返回;}//销毁所有注册表AbstractRegistryFactory.destroyAll();//销毁所有协议destroyProtocols();}这一步过程:从注册中心销毁所有发布的服务,取消订阅,断开与注册中心的连接,执行Protocol的destroy()方法,销毁所有的Invokers和Exporter,关闭Server,关闭JVM,实际测试Dubbo的优雅离线功能,如上图中,搭建Nacos注册中心、Dubbo服务器和消费者。消费者一直调用一个接口,服务端执行System.exit(-1)方法查看执行过程。日志打印如下。从日志来看,正常下线是有效的。上述的企业级优雅离线的离线方式还存在一定的问题。开源的Dubbo可以通过shutdownHook和QoS实现优雅下线,但是有一定的开发工作量,对Dubbo有版本要求,还存在一些遗留问题。最终影响正常使用。阿里云MSE提供无损离线离线功能。当然可能收费,但是接入简单,适合大型系统。MSE配置无损离线。小结本文介绍无损离线。中间脏数据的问题,下一篇讲无损在线