Статьи

MicroServices. Часть 3. Регистрация и обнаружение Spring Cloud Service

В мире микросервисов Service Registry and Discovery играет важную роль, потому что мы, скорее всего, запускаем несколько экземпляров сервисов, и нам нужен механизм для вызова других сервисов без жесткого кодирования их имен узлов или номеров портов. В дополнение к этому в облачных средах экземпляры сервисов могут появляться и отключаться в любое время. Поэтому нам нужен механизм автоматической регистрации и обнаружения сервисов. Spring Cloud предоставляет функции Service Registry and Discovery , как обычно, с несколькими вариантами. Мы можем использовать Netflix Eureka или Consul для обслуживания реестра и обнаружения. В этом посте мы узнаем, как использовать SpringCloud Netflix Eureka для Service Registry and Discovery.

Микроуслуги с использованием Spring Boot и Spring Cloud

В моем предыдущем сообщении, 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
@SpringBootApplication
public 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-registry
server.port=8761
eureka.instance.hostname=localhost
eureka.instance.client.registerWithEureka=false
eureka.instance.client.fetchRegistry=false
eureka.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
@Slf4j
public 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-service
server.port=8282
eureka.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.jar
 
java -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
@SpringBootApplication
public 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
@Slf4j
public 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 =
                    restTemplate.getForEntity("http://inventory-service/api/inventory/{code}",
                                                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;
    }
}
 
@Data
public 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, являются их собственными.