В мире микросервисов Service Registry and Discovery играет важную роль, потому что мы, скорее всего, запускаем несколько экземпляров сервисов, и нам нужен механизм для вызова других сервисов без жесткого кодирования их имен узлов или номеров портов. В дополнение к этому в облачных средах экземпляры сервисов могут появляться и отключаться в любое время. Поэтому нам нужен механизм автоматической регистрации и обнаружения сервисов. Spring Cloud предоставляет функции Service Registry and Discovery , как обычно, с несколькими вариантами. Мы можем использовать Netflix Eureka или Consul для обслуживания реестра и обнаружения. В этом посте мы узнаем, как использовать SpringCloud Netflix Eureka для Service Registry and Discovery.
Микроуслуги с использованием Spring Boot и Spring Cloud
- Часть 1. MicroServices: Spring Boot и Spring Cloud Обзор
- Часть 2. MicroServices: управление конфигурацией с помощью Spring Cloud Config и Vault
- Часть 3. MicroServices: реестр и обнаружение Spring Cloud Service
В моем предыдущем сообщении, MicroServices — Часть 2. Управление конфигурацией с помощью Spring Cloud Config и Vault , мы узнали, как хранить параметры конфигурации на внешнем сервере конфигурации и как безопасно хранить секреты в Vault.
В этом посте мы собираемся узнать:
- Что такое сервисный реестр и обнаружение?
- Сервисный реестр Spring Cloud Netflix на основе Eureka
- Регистрация микросервисов в качестве клиентов Eureka
- Обнаружение других услуг с помощью Eureka Client
Что такое сервисный реестр и обнаружение?
Предположим, у нас есть 2 службы каталогов и служба инвентаризации, и мы работаем с 2 экземплярами службы инвентаризации по адресу http: // localhost: 8181 / и http: // localhost: 8282 /. Теперь предположим, что мы хотим вызвать некоторую конечную точку REST службы инвентаризации из службы каталогов. Какой URL мы должны нажать? Как правило, в этих сценариях мы используем балансировщик нагрузки, настраивая эти 2 URL-адреса для делегирования, и мы будем вызывать конечную точку REST для URL-адреса балансировщика нагрузки. Хорошо.
Но что, если вы хотите динамически раскручивать новые экземпляры в зависимости от нагрузки? Даже если вы собираетесь запустить только несколько серверных узлов, ручное обновление сведений о серверном узле в конфигурации балансировщика нагрузки подвержено ошибкам и утомительно. Вот почему нам нужен механизм автоматической регистрации службы и мы можем вызывать службу, используя некоторый логический идентификатор службы вместо использования определенных IP-адресов и номеров портов.
Мы можем использовать Netflix Eureka Server, чтобы создать реестр услуг и сделать наши микросервисы клиентами Eureka, чтобы при запуске микросервиса он автоматически регистрировался на Eureka Server с логическим идентификатором сервиса. Затем другие микросервисы, которые также являются клиентами Eureka, могут использовать Service ID для вызова конечных точек REST.
Spring Cloud позволяет очень легко создавать реестр служб и обнаруживать другие службы с помощью Load Balanced RestTemplate.
Сервисный реестр Spring Cloud Netflix Eureka
Давайте создадим реестр служб с помощью Netflix Eureka, который представляет собой не что иное, как приложение SpringBoot с Eureka Server Starter.
|
1
2
3
4
|
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency> |
Нам нужно добавить аннотацию @EnableEurekaServer, чтобы сделать наше приложение SpringBoot реестром сервисов на основе сервера Eureka.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer@SpringBootApplicationpublic class ServiceRegistryApplication { public static void main(String[] args) { SpringApplication.run(ServiceRegistryApplication.class, args); }} |
По умолчанию каждый сервер Eureka также является клиентом Eureka, и ему необходим как минимум один URL-адрес службы для поиска партнера. Поскольку у нас будет один узел Eureka Server (автономный режим), мы собираемся отключить это поведение на стороне клиента, настроив следующие свойства в файле application.properties.
application.properties
|
1
2
3
4
5
6
|
spring.application.name=service-registryserver.port=8761eureka.instance.hostname=localhosteureka.instance.client.registerWithEureka=falseeureka.instance.client.fetchRegistry=falseeureka.instance.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ |
Netflix Eureka Service предоставляет пользовательский интерфейс, где мы можем увидеть все подробности о зарегистрированных сервисах.
Теперь запустите ServiceRegistryApplication и получите доступ к http: // localhost: 8761, который отобразит пользовательский интерфейс, подобный скриншоту ниже.
Регистрация микросервисов в качестве клиентов Eureka
В части 2 MicroServices: Управление конфигурацией с помощью Spring Cloud Config и Vault мы создали каталог-сервис. Позвольте нам сделать эту услугу в качестве клиента Eureka и зарегистрироваться на сервере Eureka.
Добавьте стартер Eureka Discovery в каталог-сервис, который добавит следующую зависимость.
|
1
2
3
4
|
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency> |
Когда spring-cloud-starter-netflix-eureka-client находится в classpath, нам просто нужно настроить свойство eureka.client.service-url.defaultZone в application.properties для автоматической регистрации на сервере Eureka.
|
1
|
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ |
Когда служба зарегистрирована на сервере Eureka, она продолжает посылать пульс в течение определенного интервала. Если сервер Eureka не получил пульс от какого-либо экземпляра службы, он будет считать, что экземпляр службы отключен, и удалит его из пула.
С этой конфигурацией запустите каталог-сервис и посетите http: // localhost: 8761. Вы должны увидеть, что каталог-сервис зарегистрирован под SERVICE ID как CATALOG-SERVICE . Вы также можете заметить состояние как UP (1), что означает, что службы запущены и работают, и запущен один экземпляр службы каталогов .
Давайте запустим еще один экземпляр службы каталогов на другом порту, используя следующую команду.
|
1
|
java -jar -Dserver.port=9797 target/catalog-service-0.0.1-SNAPSHOT-exec.jar |
Теперь, если вы перейдете по адресу http: // localhost: 8761, вы заметите, что 2 экземпляра службы каталогов зарегистрированы, и вы также можете увидеть их имя хоста: сведения о порте.
Обнаружение других услуг с помощью Eureka Client
В предыдущем разделе мы узнали, как зарегистрировать службу в качестве клиента Eureka, а также попытались зарегистрировать несколько экземпляров одной и той же службы.
Теперь мы создадим еще одну службу инвентаризации микросервисов, которая предоставляет конечную точку REST http: // localhost: 8282 / api / invenory / {productCode}, которая выдаст текущее доступное количество в качестве ответа.
|
1
2
3
4
|
{ productCode: "P001", availableQuantity: 250} |
Создайте приложение SpringBoot со службой инвентаризации с помощью стартеров Web , JPA , H2 / MySQL , Actuator , Config Client и Eureka Discovery .
Создайте контроллер REST для возврата данных инвентаризации для данного кода продукта.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
@RestController@Slf4jpublic class InventoryController { private final InventoryItemRepository inventoryItemRepository; @Autowired public InventoryController(InventoryItemRepository inventoryItemRepository) { this.inventoryItemRepository = inventoryItemRepository; } @GetMapping("/api/inventory/{productCode}") public ResponseEntity<InventoryItem> findInventoryByProductCode(@PathVariable("productCode") String productCode) { log.info("Finding inventory for product code :"+productCode); Optional<InventoryItem> inventoryItem = inventoryItemRepository.findByProductCode(productCode); if(inventoryItem.isPresent()) { return new ResponseEntity(inventoryItem, HttpStatus.OK); } else { return new ResponseEntity(HttpStatus.NOT_FOUND); } }} |
Пожалуйста, посмотрите на GitHub Repository для кода InventoryItem, InventoryItemRepository и т. Д.
Зарегистрируйте инвентаризацию на сервере Eureka, настроив Eureka serviceUrl в src / main / resources / bootstrap.properties .
|
1
2
3
|
spring.application.name=inventory-serviceserver.port=8282eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ |
Теперь создайте инвентарь-сервис и запустите 2 экземпляра, выполнив следующие команды.
|
1
2
3
|
java -jar -Dserver.port=9898 target/inventory-service-0.0.1-SNAPSHOT-exec.jarjava -jar -Dserver.port=9999 target/inventory-service-0.0.1-SNAPSHOT-exec.jar |
Теперь вы можете посетить Eureka Dashboard http: // localhost: 8761 / и увидеть 2 зарегистрированных инвентаря.
Предположим, мы хотим вызвать конечную точку REST службы инвентаризации из службы каталогов. Мы можем использовать RestTemplate для вызова конечной точки REST, но запущено 2 экземпляра.
Мы можем зарегистрировать RestTemplate как бин Spring с аннотацией @LoadBalanced . Шаблон RestTemplate с аннотацией @LoadBalanced будет внутренне использовать Ribbon LoadBalancer для разрешения ServiceID и вызывать конечную точку REST, используя один из доступных серверов.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@SpringBootApplicationpublic class CatalogServiceApplication { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(CatalogServiceApplication.class, args); }} |
Теперь мы можем использовать RestTemplate для вызова конечной точки службы инвентаризации по адресу http: // inventory-service / api / inventory / {productCode} .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
@Service@Transactional@Slf4jpublic class ProductService { private final ProductRepository productRepository; private final RestTemplate restTemplate; @Autowired public ProductService(ProductRepository productRepository, RestTemplate restTemplate) { this.productRepository = productRepository; this.restTemplate = restTemplate; } public Optional<Product> findProductByCode(String code) { Optional<Product> productOptional = productRepository.findByCode(code); if(productOptional.isPresent()) { log.info("Fetching inventory level for product_code: "+code); ResponseEntity<ProductInventoryResponse> itemResponseEntity = ProductInventoryResponse.class, code); if(itemResponseEntity.getStatusCode() == HttpStatus.OK) { Integer quantity = itemResponseEntity.getBody().getAvailableQuantity(); log.info("Available quantity: "+quantity); productOptional.get().setInStock(quantity> 0); } else { log.error("Unable to get inventory level for product_code: "+code + ", StatusCode: "+itemResponseEntity.getStatusCode()); } } return productOptional; }}@Datapublic class ProductInventoryResponse { private String productCode; private int availableQuantity;} |
Обратите внимание, что вместо http: // localhost: 9898 / api / inventory / {code} или http: // localhost: 9999 / api / inventory / мы использовали http: // inventory-service / api / inventory / {code} {код} напрямую.
Благодаря такому механизму автоматической регистрации и обнаружения служб нам не нужно беспокоиться о том, сколько экземпляров запущено, каковы их имена хостов и порты и т. Д.
Вы можете найти исходный код этой статьи по адресу https://github.com/sivaprasadreddy/spring-boot-microservices-series
Резюме
В этом посте мы узнали, как использовать Spring Cloud Netflix Eureka для Service Registry and Discovery . В следующем посте мы рассмотрим реализацию шаблона прерывателя цепи с использованием Netflix Hystrix .
| Опубликовано на Java Code Geeks с разрешения Сивы Редди, партнера нашей программы JCG . См. Оригинальную статью здесь: MicroServices. Часть 3. Регистрация и обнаружение Spring Cloud Service.
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |
