当前位置:   article > 正文

k8s环境中dubbo故障容器自动隔离功能的实现_k8s故障隔离机制

k8s故障隔离机制

背景

          企业云服务,全是企业客户、代账中介客户,生产环境偶发个别容器dubbo线程池爆满,通过研究发现问题发生时会同时伴随数据库性能抖动、容器CPU爆满,通过和业务系统的开发人员了解到,系统中存在重接口和批量接口的情况,这些接口也往往和客户的数据量大小有关,这些存在隐患的接口并没有得到合理的控制,它们和轻量级接口位于同一个微服务中,就可能相互影响。这些重接口可能造成的问题 1、影响数据库的稳定性;2、影响cpu和内存的稳定性;一旦产生影响,往往伴随着轻量级接口不能及时得到响应,dubbo线程池会被逐渐占满,进而报错。

           可能有同学会说,dubbo不是会自动隔离故障节点吗?实际上对于彻底死掉没有心跳的节点确实会自动隔离,但是对于半死不活,心跳还在,但压力很大的节点并不会得到隔离,这就需要我们自己来解决这类刺手问题。

解决思路

           一方面我们启用了dubbo的重试机制,在发生线程池满错误的情况下能自动容错到其它容器,保证用户侧无感知。

           另一方面我们要防患于未然,把危机扼杀在摇篮里,我们对dubbo的线程池活跃线程(active)数量进行了监控,设置了临界值,健康检查线程每间隔30秒进行一次检测,一旦检测到异常,就会触发一系列的防护措施:

1、dubbo服务隔离可以及时引流消费者流量到其它正常的提供者

2、邮件和短信告警可以让架构师和运维人员及时关注问题容器情况,如果无法自愈,需要运维干预下重启容器。

3、cpu、内存和线程栈信息记录日志,有助于业务开发人员解决接口存在的问题

架构图

b5bb2b023ed68d0e8cd985dc03d4b025.png

原理

1、根据dubbo-admin的原理,注册override配置信息到注册中心;

2、消费者通过注册中心收到事件通知,根据规则进行 override  url与provider  url以及 consumer url 合并过滤操作;

服务隔离部分的实现代码

1、隔离与恢复事件

  1. @Autowired
  2. private HealthCheckConfig checkConfig;
  3. @Autowired
  4. private RegistryService registryService;
  5. @Autowired
  6. private ProtocolConfig protocolConfig;
  7. @EventListener
  8. public void startIsolate(DubboThreadPoolHighEvent event) {
  9. //开启隔离
  10. log.error("故障节点隔离开始:" + event.getActiveCount());
  11. disableProvider(true);
  12. log.error("故障节点隔离成功");
  13. }
  14. @EventListener
  15. public void stopIsolate(DubboThreadPoolNormalEvent event) {
  16. //关闭隔离
  17. log.error("故障节点取消隔离开始" + event.getActiveCount());
  18. disableProvider(false);
  19. log.error("故障节点取消隔离成功");
  20. }
  21. private void disableProvider(boolean disable) {
  22. try {
  23. if (!checkConfig.getHealthCheckIsolateEnable()) {
  24. log.error("未启用健康检查隔离服务");
  25. return;
  26. }
  27. Map<String, Object> beansWithAnnotation = SpringUtil.getApplicationContext().getBeansWithAnnotation(Service.class);
  28. //override://192.168.2.100:23881/a.b.c.XxxService?
  29. // category=configurators&disabled=true&dynamic=false&enabled=true
  30. String ip = NetUtils.getLocalHost();
  31. Integer port = protocolConfig.getPort();
  32. //---
  33. for (Object value : beansWithAnnotation.values()) {
  34. Class<?>[] itfs = value.getClass().getInterfaces();
  35. Class<?> itf = itfs[0];
  36. URL url = new URL(Constants.OVERRIDE_PROTOCOL, ip, port, itf.getCanonicalName());
  37. url = url.addParameter("category", "configurators");
  38. url = url.addParameter("disabled", true);
  39. url = url.addParameter("dynamic", false);
  40. url = url.addParameter("enabled", true);
  41. if (disable) {
  42. registryService.register(url);
  43. log.error("register:" + url.toString());
  44. } else {
  45. registryService.unregister(url);
  46. log.error("unregister:" + url.toString());
  47. }
  48. }
  49. }catch (Exception e){
  50. log.error("isolate error ",e);
  51. }
  52. }

2、优雅关机事件

  1. @EventListener
  2. public void clearIsolate(AppCloseEvent event) {
  3. if (event.getIsolateStatus()) {
  4. log.error("关闭之前取消隔离" + event.getIsolateStatus());
  5. disableProvider(false);
  6. log.error("关闭之前取消隔离成功");
  7. try {
  8. TimeUnit.SECONDS.sleep(checkConfig.getHealthCheckShutdownHookWaitTime());
  9. }catch (Exception e){
  10. }
  11. }else{
  12. log.error("--isolate status:false--");
  13. }
  14. }

3、暴力关机情况的处理

  1. @EventListener
  2. public void initIsolate(AppOpenEvent event){
  3. log.error("--init isolate status--");
  4. disableProvider(false);
  5. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/169540
推荐阅读
相关标签
  

闽ICP备14008679号