当前位置:   article > 正文

Eureka心跳检测

eureka心跳检测

前言

注册中心的心跳机制有两种形式:客户端主动上报和客户端被动响应。Eureka属于是主动上报类型的,Client通过renew机制频繁的向Server发送消息,通知Server它还活着,不要将其从服务列表中剔除,但是我们renew仅仅是监控Client是否存活,并不会去检测Client依赖的服务是否存活

image-20200410233537737

从图中我们发现Client123和Client456两个客户端均依赖了第三方组件,并且MySQL同时宕机了。

  • Client123使用了Eureka自带的renew机制,renew最基础的就是调一下Server的/apps/{appName}/{instanceId}?status=&lastDirtyTimestamp=接口,正常情况下Client启动后的status为UP,所以只要Client自身服务不出问题,永远都是UP,默认的指示器是CompositeHealthIndicator,默认的管理器为EurekaHealthCheckHandler
  • Client456通过扩展HealthIndicator接口和HealthCheckHandler接口,然后来自定义需要监控的内容

默认健康监控组件

在类DiscoveryClient#getHealthCheckHandler方法中选择需要使用的健康管理器

  1. public HealthCheckHandler getHealthCheckHandler() {
  2. HealthCheckHandler healthCheckHandler = this.healthCheckHandlerRef.get();
  3. if (healthCheckHandler == null) {
  4. if (null != healthCheckHandlerProvider) {
  5. healthCheckHandler = healthCheckHandlerProvider.get();
  6. } else if (null != healthCheckCallbackProvider) {
  7. healthCheckHandler = new HealthCheckCallbackToHandlerBridge(healthCheckCallbackProvider.get());
  8. }
  9. if (null == healthCheckHandler) {
  10. healthCheckHandler = new HealthCheckCallbackToHandlerBridge(null);
  11. }
  12. this.healthCheckHandlerRef.compareAndSet(null, healthCheckHandler);
  13. }
  14. return this.healthCheckHandlerRef.get();
  15. }

方法调用流程图

image-20200411021953543

自定义健康监控

  1. 自定义监控组件

    1. @Component
    2. public class HealthPolicyBean implements InitializingBean {
    3. @Resource
    4. private RedisTemplate<String, Object> redisTemplate;
    5. /**
    6. * 调度线程池
    7. */
    8. private ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
    9. /**
    10. * 数据库健康情况
    11. */
    12. public static boolean dbHealth = true;
    13. /**
    14. * Redis健康情况
    15. */
    16. public static boolean redisHealth = true;
    17. /**
    18. * MongoDB健康情况
    19. */
    20. public static boolean mongoHealth = true;
    21. @Override
    22. public void afterPropertiesSet() throws Exception {
    23. // 创建调度器
    24. ThreadPoolExecutor heartbeatExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS,
    25. new SynchronousQueue<>(),
    26. new ThreadFactoryBuilder().setNameFormat("redis-HeartbeatExecutor-%d").setDaemon(true).build());
    27. TimedSupervisorTask task = new TimedSupervisorTask("redis-heartbeat", scheduled, heartbeatExecutor, 10,
    28. TimeUnit.SECONDS, 100, new RedisTimer());
    29. scheduled.schedule(task, 10, TimeUnit.SECONDS);
    30. }
    31. /**
    32. * 监控Redis状态
    33. */
    34. protected class RedisTimer implements Runnable {
    35. @Override
    36. public void run() {
    37. try {
    38. List<RedisClientInfo> clientList = redisTemplate.getClientList();
    39. if (clientList == null || clientList.isEmpty()) {
    40. HealthPolicyBean.redisHealth = false;
    41. } else {
    42. HealthPolicyBean.redisHealth = true;
    43. }
    44. } catch (Exception e) {
    45. HealthPolicyBean.redisHealth = false;
    46. }
    47. }
    48. }
    49. }
  2. 自定义HealthIndicator

    1. /**
    2. * Cc健康指示器
    3. */
    4. @Component
    5. public class CcHealthIndicator implements HealthIndicator {
    6. @Override
    7. public Health health() {
    8. if (HealthPolicyBean.dbHealth && HealthPolicyBean.redisHealth && HealthPolicyBean.mongoHealth) {
    9. // 当所有组件都正常时才返回UP
    10. return new Health.Builder(Status.UP).build();
    11. } else {
    12. return new Health.Builder(Status.DOWN).build();
    13. }
    14. }
    15. }
  3. 自定义HealthCheckHandler

    1. /**
    2. * Cc健康管理器
    3. */
    4. @Component
    5. public class CcHealthCheckHandler implements HealthCheckHandler {
    6. @Autowired
    7. private CcHealthIndicator ccHealthIndicator;
    8. @Override
    9. public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) {
    10. if (ccHealthIndicator.health().getStatus().equals(Status.UP)) {
    11. return InstanceInfo.InstanceStatus.UP;
    12. }
    13. return InstanceInfo.InstanceStatus.DOWN;
    14. }
    15. }

    方法调用流程图

    image-20200411021933621

区别

我们打开Redis服务,启动Eureka Server、Client123和Client456。

  • Redis运行中

    Redis正常运行时,两个服务都处于正常情况

    image-20200411022923590

  • Redis停止

    将Redis服务停掉,等待一个renew周期后,服务状态发生变化,使用默认HealthCheckHandler的CUSER-SERVICE的status仍然为UP,而我们自定义HealthCheckHandler的EUREKA-HEALTH服务的status已经变成了DOWN,符合正常要求。

    image-20200411023355326

总结

在实际的生产工作中,尽量不要使用默认的HealthCheckHandler,不然就算是我们项目的MySQL、Redis、MongoDB、MQ都挂掉了,只要项目的进程还存活,那么status就很大的可能是UP,但实际上项目已经无法正常提供服务了,会给我们的项目带来很大的麻烦。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/838940
推荐阅读
相关标签
  

闽ICP备14008679号