☰
Current Page
Main Menu
Home
Home
Editing
优雅shutdown
Edit
Preview
h1
h2
h3
default
Set your preferred keybinding
default
vim
emacs
markdown
Set this page's format to
AsciiDoc
Creole
Markdown
MediaWiki
Org-mode
Plain Text
RDoc
Textile
Rendering unavailable for
BibTeX
Pod
reStructuredText
Help 1
Help 1
Help 1
Help 2
Help 3
Help 4
Help 5
Help 6
Help 7
Help 8
Autosaved text is available. Click the button to restore it.
Restore Text
# graceful shutdown 方案设计文档 ## 1. 现状分析 ### 1.1 当前问题 1. **引擎直接关闭**:目前的引擎关闭操作是直接关闭,没有进行额外的收尾操作。 2. **数据丢失风险**: - **应用更新和添加**:在更新或添加应用时会导致容器重启,这对于一些应用(如 IoT)来说,由于无法及时消费队列中的数据,会导致数据丢失。 - **Hazelcast 组网**:多个节点直接关闭时,由于某一写分片来不及备份,可能导致数据丢失。 3. **缺乏优雅关闭机制**:当前的关闭操作是直接和突兀的,没有给业务一定的缓冲时间。 ## 2. 改进方案和实现 ### 2.1 配置 Spring 优雅关闭机制 通过配置 Spring 的优雅关闭机制,可以在 JVM 关闭时优雅地关闭 Spring 应用上下文,避免数据丢失。 1. 检查容器配置中,是否配置了`terminationGracePeriodSeconds`字段,不配置(默认为30)或配置为30即可 2. 需要在application-dev.properties文件里添加如下配置 #### 配置文件(application.properties) ```properties server.shutdown=graceful spring.lifecycle.timeout-per-shutdown-phase=30s ``` #### SpringApplication 类 ```java private void registerShutdownHook(ConfigurableApplicationContext context) { if (this.registerShutdownHook) { Thread shutdownHook = new Thread(() -> { try { context.close(); } catch (Exception ex) { // Handle exception... } }); Runtime.getRuntime().addShutdownHook(shutdownHook); } } ``` 通过 `Runtime.getRuntime().addShutdownHook(shutdownHook);` 监听 k8s 发送的 SIGTERM 信号。 ### 2.2 实现 DisposableBean 接口 通过实现 `DisposableBean` 接口,可以在 Spring 容器关闭时执行一些自定义的销毁逻辑。 #### 示例代码 ```java @RestController @CrossOrigin public class RpcController implements DisposableBean { ... @Override public void destroy() throws Exception { long start = System.currentTimeMillis(); logger.warn("\n\n\n ###################### iidp server destroy start at {}\n\n\n", start); // 自定义销毁逻辑 ... long end = System.currentTimeMillis(); logger.warn("\n\n\n ###################### iidp server destroy finish at {}, cost: {} ms", end, end - start); } ... } ``` ### 2.3 优雅关闭 Hazelcast 通过优雅关闭 Hazelcast 当前成员,避免数据丢失。 #### 示例代码 ```java // 优雅关闭 Hazelcast 当前成员,避免数据丢失 // 参考: https://docs.hazelcast.com/hazelcast/5.5/maintain-cluster/shutdown Hazelcast.getInstance().shutdown(); ``` ### 2.4 触发销毁事件 在关闭容器时,给当前容器中的所有应用发送销毁事件。 #### 示例代码 ```java public void destroyEvent() { // 给当前容器所有的 app 发送 destroy event Meta meta = new Meta(Meta.SUPERUSER, new HashMap<>()); Map<String, AppDataInfo> appDataInfoMap = EngineContainer.getBussinessAppGroupContainer().getAppDataInfoMap(); Map<String, AppDataInfo> appDataInfoMap2 = EngineContainer.getBaseAppGroupContainer().getAppDataInfoMap(); List<AppDataInfo> appDataInfoList = new ArrayList<>(appDataInfoMap.values()); appDataInfoList.addAll(appDataInfoMap2.values()); for (AppDataInfo appInfo : appDataInfoList) { Map<String, List<String>> events = appInfo.getEvents(); if (events == null || events.isEmpty()) { continue; } List<String> methodList = events.get(EventType.DESTROY.getType()); if (methodList == null || methodList.isEmpty()) { continue; } meta.addArgument("app", appInfo.getName()); meta.addArgument(MetaConstant.TAG, appInfo.getTag()); logger.info("============== App [{}] 销毁事件 {} 开始 ==============", appInfo.getName(), methodList); for (String method : methodList) { try { String[] modelMethod = method.split(MetaConstant.METHOD_SEPARATOR); if (modelMethod.length == 3 && "ASYNC".equals(modelMethod[2])) { meta.get(modelMethod[0]).callAsync(modelMethod[1]); } else { meta.get(modelMethod[0]).call(modelMethod[1]); } } catch (Exception ex) { logger.error(String.format("执行应用: %s 事件报错", appInfo.getNameTag()), ex); } } logger.info("============== App [{}] 销毁事件 {} 结束 ==============", appInfo.getName(), methodList); } } ``` ### 2.5 app定义destroy销毁事件 在app中的app.json文件中定义销毁事件 ```json "events":{ "destroy": [ "trace_whitelist::destroy" # 新增destroy事件 ], "startUp": [ "trace_whitelist::register" ], "register" : [ ], "login": [ ] } ``` ## 3. 总结 通过以上改进措施,可以实现系统的优雅关闭,避免数据丢失,提高系统的可靠性和稳定性。这些措施包括配置 Spring 的优雅关闭机制、实现 `DisposableBean` 接口、优雅关闭 Hazelcast 以及触发销毁事件。通过这些改进,可以为业务提供一定的缓冲时间,确保数据的完整性和一致性。
Uploading file...
Sidebar
[[_TOC_]]
Edit message:
Cancel