Spring Cloud Netflix: Eureka по-русски

Kirill Sereda
6 min readJun 3, 2019

--

Привет.

В последнее время я сильно заинтересовался стеком, предоставляемый компанией Netflix. В данной статье хочу поделиться своим пониманием касательно Eureka.

На русском языке очень мало информации по стеку Netflix.

И правильно, потому что надо читать официальную документацию, там вы найдете больше всего. Но я все же решил рассказать “своими словами” чтобы сложилась более ясная картина при изучении данного стека для тех, кто предпочитает русскоязычную литературу.

Планирую обновлять статьи по мере изучения нового материала. Если у вас есть предложения на этот счет, буду рад выслушать.

Eureka Server — это приложение, которое содержит информацию обо всех клиентских сервисных приложениях.
Каждый микросервис регистрируется на сервере Eureka, и Eureka знает все клиентские приложения, работающие на каждом порту и IP-адресе.
Eureka Server также известен как Discovery Server.

Его аналоги:
- Consul
- Zookeeper
- Cloud Foundry

Если простыми словами, то — это сервер имен или реестр сервисов. Обязанность — давать имена каждому микросервису.
Регистрирует микросервисы и отдает их ip другим микросервисам.

Таким образом, каждый сервис регистрируется в Eureka и отправляет эхо-запрос серверу Eureka, чтобы сообщить, что он активен.
Для этого сервис должен быть помечен как @EnableEurekaClient, а сервер @EnableEurekaServer.

При указании аннотаций @EnableDiscoveryClient тоже отработает, т.к. Eureka является Discovery сервисом, но вот в случае если использовать любой другой Dicovery сервис и использовать аннотацию @EnableEurekaClient, так уже не прокатит.

Минимальные настройки:

В файле application.properties:

# По умолчанию использует порт 8761
server.port=8761

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

или использовать application.yml файл:

eureka:
client:
registerWithEureka: false
fetchRegistry: false

server:
port: 8761

Также необходимо указать соответствующую аннотацию @EnableEurekaServer в основном файле проекта.

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}

}

Это минимальные необходимые настройки для запуска Eureka Server.

Запустите проект и перейдите по адресу

http://localhost:8761

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

Аннотация @EnableEurekaClient сообщает платформе следующее:
Что данный сервис является экземпляром какого-то микросервиса и просит зарегистрировать его на сервере Eureka, также хочет узнать другие службы, которые зарегистрированы в Eureka Server.

Пару слов про понятия, в которых многие путаются.

- Eureka Server

Он содержит реестр служб и REST API, которые можно использовать для регистрации службы, отмены регистрации службы и определения местоположения других служб.

- Eureka Service

Любое приложение, которое можно найти в реестре служб Eureka Server и которое может быть обнаружено другими службами. Служба имеет определенный ID (его еще называют VIP) который может ссылаться на один или несколько экземпляров одного и того же приложения.

- Eureka Instance

Любое приложение, которое регистрируется на Eureka Server для обнаружения другими.

- Eureka Client

Любое приложение, которое может обнаружить службы. Он только запрашивает реестр служб у Eureka Server, чтобы определить запущенные экземпляры микросервисов.

Нашел картинку на просторах интернета

Приложение может быть как Eureka Instance и Eureka Client одновременно, приложениям часто нужно сделать себя доступными для использования другими (чтобы они были экземпляром), и в то же время им нужно обнаружить другие службы (чтобы они были клиентами).

Но Eureka Client не должен являться экземпляром Eureka Instance, т.к. иногда приложение не может ничего предложить другим и оно только вызывает другие сервисы.

Можно запретить ему регистрироваться в качестве экземпляра:

eureka.client.register-with-eureka = false

Другими словами Eureka Client регистрируется в Eureka Server.
Поскольку Eureka Instance регистрируется в Eureka Server, он тоже является клиентом.
Т.к. Eureka Service предлагает API другим, следовательно его могут обнаружить другие, поэтому он является экземпляром.

Как это работает ?

По умолчанию клиент Eureka запускается в состоянии `STARTING`, что дает экземпляру возможность выполнить инициализацию для конкретного приложения, прежде чем он сможет обслуживать трафик.
Eureka Client сначала пытается связаться с сервером Eureka в той же зоне в облаке AWS (по умолчанию), но если он не может найти сервер, он переключается на другие зоны.
Eureka Client сбрасывает все HTTP-соединения, которые простаивали более 30 секунд, которые он создал для связи с сервером.

Клиент взаимодействует с сервером следующим образом:

1) Eureka Client регистрирует информацию о запущенном экземпляре на сервере Eureka.

2) Каждые 30 секунд клиент отсылает запрос на сервер и информирует сервер о том, что экземпляр еще жив.
Если сервер не видел обновления в течение 90 секунд, он удаляет экземпляр из своего реестра.

3) Eureka Client получает информацию реестра от сервера и кэширует ее у себя локально.
Эта информация обновляется периодически (каждые 30 секунд), получая обновления между последним апдейтом и текущим.
Клиент автоматически обрабатывает дублирующую информацию.

4) Получив обновления, клиент сверяет информацию с сервером, сравнивая количество экземпляров, возвращаемых сервером, и если информация по какой-либо причине не совпадает, вся информация реестра извлекается снова.
Клиент получает информацию в сжатом формате JSON, используя клиент jersey apache.

5) При завершении работы клиент отправляет запрос отмены на сервер.
Таким образом экземпляр удаляется из реестра экземпляров сервера.
Eureka использует протокол, который требует, чтобы клиенты выполняли явное действие отмены регистрации.

DiscoveryManager.getInstance().shutdownComponent()

Клиенты, которые использовали 3 неудачные попытки синхронизации с сервером с интервалом в 30 секунд будут удалены автоматически.

По умолчанию Eureka Client используют Jersey и Jackson вместе с JSON для связи с Eureka Server.
Можно переопределить механизм по умолчанию, чтобы настроить свой кастомный.

Есть такое понятие, как время запаздывания (или Time Lag):

Все операции с Eureka Client могут занять некоторое время для отражения на Eureka Server, а затем и на других Eureka Client.
Это связано с кэшированием полезных данных на сервере, которые периодически обновляются для отображения новой информации.
Клиенты также периодически получают эти обновления. В итоге может потребоваться до 2 минут, чтобы изменения распространялись на всех клиентов.

Режим самосохранения:

Eureka Server перейдет в режим самосохранения, если обнаружит, что зарегистрированное количество клиентов превысило ожидаемое количество и прервало соединения для связи с сервером.
Это было сделано для того, чтобы гарантировать, что какие-либо сетевые события (большие нагрузки или проблемы в сети) не уничтожат данные реестра Eureka Server.

Чтобы установить порог самосохранения, надо указать свойство в файле properties:

eureka.renewalPercentThreshold=[0.0, 1.0]

Чтобы отключить режим самосохранения, необходимо:

eureka.enableSelfPreservation=false

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

Взаимодействие серверов между собой

Серверы Eureka взаимодействуют друг с другом, используя тот же механизм, который используется между клиентом и сервером.
Когда сервер запускается, он пытается получить всю информацию реестра экземпляра от соседнего узла.
Если при получении информации от узла возникает проблема, сервер проверяет все равноправные узлы.
В случае проблем сервер пытается защитить уже имеющуюся у него информацию.
Например может быть сценарий массового отключения, в результате которого клиенты могут получить экземпляры, которые больше не существуют.
Лучшая защита при таком сценарии — быстрое отключение и проверка других серверов.
Когда сервер запускается и в случае, когда он не может получить информацию о реестре от соседнего узла, он ждет 5 минут, чтобы клиенты могли зарегистрировать свою информацию.

Если появляются проблемы в сети, то между узлами могут возникнуть следующие проблемы:

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

  • регистрация клиентов может происходить на потерянном сервере

Б — безопасность

Если вы хотите подключиться по HTTPS, вы можете прописать:

eureka.instance.nonSecurePortEnabled=false
eureka.instance.securePortEnabled=true

В application.yml можно использовать placeholders:

eureka:
instance:
statusPageUrl: https://${eureka.hostname}/info
healthCheckUrl: https://${eureka.hostname}/health
homePageUrl: https://${eureka.hostname}/

Проверка состояния:

После успешной регистрации Eureka всегда объявляет, что приложение находится в состоянии «UP».
Это поведение можно изменить, включив проверки работоспособности Eureka.

eureka:
client:
healthcheck:
enabled: true

Работы клиентов в других зонах:

Если клиенты Eureka находятся в нескольких зонах, можно сделать так, чтобы эти клиенты использовали службы в той же зоне, где они сами находятся, прежде чем пытаться использовать службы в другой зоне.
Чтобы это настроить, необходимо правильно настроить клиенты.

# Служба А в Зоне А

eureka.instance.metadataMap.zone = zone_A
eureka.client.preferSameZoneEureka = true

# Служба А в зоне B

eureka.instance.metadataMap.zone = zone_B
eureka.client.preferSameZoneEureka = true

Компания Netflix предоставляет нам использование текущей конфигурации по умолчанию “из коробки”, но вы также можете написать свою кастомную реализацию:

Клиент:

https://github.com/Netflix/eureka/blob/master/eureka-client/src/main/java/com/netflix/discovery/DefaultEurekaClientConfig.java

Сервер:

https://github.com/Netflix/eureka/blob/master/eureka-core/src/main/java/com/netflix/eureka/DefaultEurekaServerConfig.java

Данный материал был частично взят из официальной документации.

Надеюсь эта статья поможет чуть более детально иметь представление об Eureka.

Если вы нашли неточности в описании данной статьи, вы можете написать мне на email и я с радостью вам отвечу.

Kirill Sereda

email: kirill.serada@gmail.com

skype: kirill-sereda

linkedin: www.linkedin.com/in/ksereda

--

--