Eureka никогда не отменяет регистрацию услуги

В настоящее время я столкнулся с проблемой, при которой Eureka не отменяет регистрацию зарегистрированной службы. Я взял пример сервера Eureka прямо из git hub и внес только одно изменение, eureka.enableSelfPreservation = false. Мой application.yml выглядит так:

server:
  port: 8761
eureka:
  enableSelfPreservation: false
  client:
    registerWithEureka: false
fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0

Я читал, что если 85% зарегистрированных служб перестают доставлять биения в течение 15 минут, Eureka предполагает, что проблема связана с сетью, и не отменяет регистрацию служб, которые не отвечают. В моем случае у меня работает только одна служба, поэтому я отключил режим самосохранения. Я резко прекращаю процесс, и Эврика оставляет сервис зарегистрированным на неопределенное время.

Мой клиент application.yml выглядит так:

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 3
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  appInfo:
    replicate:
      interval: 3
    initial:
      replicate:
        time: 3
spring:
  rabbitmq:
    addresses: ${vcap.services.${PREFIX:}rabbitmq.credentials.uri:amqp://${RABBITMQ_HOST:localhost}:${RABBITMQ_PORT:5672}}

Моя цель - создать демонстрацию, в которой Eureka быстро обнаруживает, что служба больше не работает, и другая запущенная служба может быстро зарегистрироваться.

На данный момент, как только клиент eureka запущен, он регистрируется за 3 секунды. Он просто никогда не отменяет регистрацию, когда служба внезапно завершается. После того, как я убью службу, на панели управления Eureka появится следующее сообщение:

СКОРАЯ МЕДИЦИНСКАЯ ПОМОЩЬ! EUREKA МОЖЕТ БЫТЬ НЕПРАВИЛЬНО ПРЕТЕНЗИВАЕТСЯ ОБ ИСПОЛЬЗОВАНИИ ЭКЗАМЕНОВ, КОГДА ИХ НЕТ. ПРОДОЛЖЕНИЕ ПРОДОЛЖАЕТСЯ МЕНЬШЕ, ЧЕМ ПОРОГ, И ПОЭТОМУ ЭКЗЕМПЛЯРЫ НЕ ПРОДОЛЖАЮТСЯ ТОЛЬКО ДЛЯ БЕЗОПАСНОСТИ.

Как я могу предотвратить такое поведение?


person lp1776    schedule 16.09.2015    source источник
comment
Какую версию Spring-Cloud вы используете?   -  person spencergibb    schedule 16.09.2015
comment
У меня есть два проекта, я использую 1.1.0 в примере, который я взял прямо с GitHub. В моем реальном проекте я использую spring-cloud-starter-config 1.0.3. Также не отменяют регистрацию клиентов.   -  person lp1776    schedule 16.09.2015
comment
Как долго вы на самом деле ждали? Мне может потребоваться некоторое время, чтобы отменить регистрацию с настройками по умолчанию.   -  person Ákos Ratku    schedule 16.09.2015
comment
Я слышал, что это должно занять от 90 секунд до 4 минут, но я ждал больше часа. Я остановил службу и пошел на обед, обновил панель управления Eureka, и служба все еще работала.   -  person lp1776    schedule 16.09.2015


Ответы (3)


Я понял, что режим самосохранения никогда не отключался. Оказывается, на самом деле это

eureka.server.enableSelfPreservation=false

(См. DefaultEurekaServerConfig Code), который я нигде не нашел документированного. Это решило мою проблему.

person lp1776    schedule 17.09.2015
comment
Запрос на перенос в репозиторий документации по этой проблеме, вероятно, будет очень полезен для многих других. ... Если кто-то еще этого не сделал. - person DtechNet; 23.09.2015

Я выполнил отмену регистрации службы, установив следующие значения

Eureka server application.yml

eureka:
  server:
    enableSelfPreservation: false

Сервис application.yml

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2

Полный пример находится здесь https://github.com/ExampleDriven/spring-cloud-eureka-example.

person Peter Szanto    schedule 07.06.2016
comment
Разве эти значения не слишком короткие? - person Mindwin; 09.08.2019
comment
значения являются всего лишь примерами, в зависимости от вашего варианта использования вам необходимо найти правильные значения. Вышеупомянутый параметр значительно повысит нагрузку на сервер eureka, но снизит риск перенаправления трафика на неработающую службу. - person Peter Szanto; 10.08.2019

После долгих испытаний, наконец, я получил решение, если какая-либо служба не была зарегистрирована на сервере Eureka из-за какой-либо проблемы. Он уведомит администратора, расширив HealthCallback API Eureka-Server. Позвольте Say Service-A зарегистрироваться на Eureka. Следовательно, Eureka Client интегрируется с Service-A и реализует следующие обратные вызовы в Service A.

Service-A [Eureka-Client] Добавьте следующие свойства в файлы свойств.

#Eureka Configuration
eureka.client.eureka-server-port=8761
eureka.client.register-with-eureka=true
eureka.client.healthcheck.enabled=false
eureka.client.prefer-same-zone-eureka=true
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone=${eurekaServerURL1}, ${eurekaServerURL2}
eureka.client.eureka.service-url.defaultZone=${eurekaServerURL1}, ${eurekaServerURL2}
eureka.instance.hostname=${hostname}
eureka.client.lease.duration=30
eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=30

Добавьте следующие файлы java.

@Component
public class EurekaHealthCheckHandler implements HealthCheckHandler, ApplicationContextAware, InitializingBean {


    static Logger logger = LoggerFactory.getLogger(EurekaHealthCheckHandler.class);

    private static final Map<Status, InstanceInfo.InstanceStatus> healthStatuses = new HashMap<Status, InstanceInfo.InstanceStatus>() {{
        put(Status.UNKNOWN, InstanceInfo.InstanceStatus.UNKNOWN);
        put(Status.OUT_OF_SERVICE, InstanceInfo.InstanceStatus.OUT_OF_SERVICE);
        put(Status.DOWN, InstanceInfo.InstanceStatus.DOWN);
        put(Status.UP, InstanceInfo.InstanceStatus.UP);
    }};

@Autowired
ComunocationService comunocationService ;
    private final CompositeHealthIndicator healthIndicator;

    private ApplicationContext applicationContext;

    public EurekaHealthCheckHandler(HealthAggregator healthAggregator) {
        Assert.notNull(healthAggregator, "HealthAggregator must not be null");
        this.healthIndicator = new CompositeHealthIndicator(healthAggregator);

        Health health = healthIndicator.health();
        logger.info(" =========== Testing =========== {}", health.toString() );
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        final Map<String, HealthIndicator> healthIndicators = applicationContext.getBeansOfType(HealthIndicator.class);
        for (Map.Entry<String, HealthIndicator> entry : healthIndicators.entrySet()) {
            logger.info("======"+ entry.getKey() +"============= "+entry.getValue());
            healthIndicator.addHealthIndicator(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus instanceStatus) {
        logger.info("============== Custome Eureka Implementation ==================="+ getHealthStatus());
        return getHealthStatus();
    }

    protected InstanceInfo.InstanceStatus getHealthStatus() {
        final Status status = healthIndicator.health().getStatus();
        return mapToInstanceStatus(status);
    }

    protected InstanceInfo.InstanceStatus mapToInstanceStatus(Status status) {
        logger.info("============== Test Custome Eureka Implementation ==================={}", status);
        if(status.equals(InstanceInfo.InstanceStatus.UP)) {
            // Send mail after configured times
              comunocationService.sendEmail("ServiceName");
        }
        if(!healthStatuses.containsKey(status)) {
            return InstanceInfo.InstanceStatus.UNKNOWN;
        }
        return healthStatuses.get(status);
    }

    public void getstatusChangeListner() {
        ApplicationInfoManager.StatusChangeListener statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
            @Override
            public String getId() {
                return "statusChangeListener";
            }
            @Override
            public void notify(StatusChangeEvent statusChangeEvent) {
                if (InstanceStatus.DOWN == statusChangeEvent.getStatus() ||
                        InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) {
                    // log at warn level if DOWN was involved
                    logger.warn("Saw local status change event {}", statusChangeEvent);
                } else {
                    logger.info("Saw local status change event {}", statusChangeEvent);
                }

            }
        };
    }


}

а также

@Configuration
public class EurekaHealthCheckHandlerConfiguration {

    @Autowired(required = false)
    private HealthAggregator healthAggregator = new OrderedHealthAggregator();

    @Bean
    @ConditionalOnMissingBean
    public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
        return new EurekaHealthCheckHandler(healthAggregator);
    }
}

Это абсолютно рабочий и хорошо протестированный код.

person Rajeev Rathor    schedule 07.05.2020