Введение в Spring Cloud Netflix - Eureka

Введение в Spring Cloud Netflix - Эврика

1. обзор

В этом руководстве мы познакомим вас с обнаружениемclient-side service через «Spring Cloud Netflix Eureka».

Client-side service discovery allows services to find and communicate with each other without hard-coding hostname and port. Единственная «фиксированная точка» в такой архитектуре состоит изservice registry, в котором каждая служба должна регистрироваться.

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

С Netflix Eureka каждый клиент может одновременно выступать в роли сервера, чтобы реплицировать свой статус на подключенный узел. Другими словами, клиент получает список всех подключенных одноранговых узловservice registry и выполняет все дальнейшие запросы к любым другим службам с помощью алгоритма балансировки нагрузки.

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

Для достижения цели этой статьи мы реализуем триmicroservices:

  • аservice registry (Eureka Server),

  • сервисREST, который регистрируется в реестре (Eureka Client) и

  • веб-приложение, которое использует службуREST в качестве клиента с учетом реестра (Spring Cloud Netflix *Feign Client*).

    == Дальнейшее чтение:

Руководство по Spring Cloud Netflix - Hystrix

В статье показано, как настроить запасную логику приложения с помощью Spring Cloud Hystrix.

Read more

Весенний отдых с прокси Zuul

Изучение использования прокси Zuul для Spring REST API, работа с CORS и ограничением политики того же источника в браузере.

Read more

2. Эврика сервер

РеализоватьEureka Server для реестра служб так же просто, как:

  1. добавлениеspring-cloud-starter-netflix-eureka-server в зависимости

  2. включить сервер Eureka в@SpringBootApplication, аннотируя его@EnableEurekaServer

  3. настроить некоторые свойства

Но мы будем делать это шаг за шагом.

Сначала мы создадим новый проект Maven и поместим в него зависимости. Обратите внимание, что мы импортируемspring-cloud-starter-parent во все проекты, описанные в этом руководстве:


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-server



    
        
            org.springframework.cloud
            spring-cloud-starter-parent
            Greenwich.RELEASE
            pom
            import
        
    

Примечание: мы можем проверить последние выпуски Spring Cloud вthe Spring’s Projects documentation.

Далее мы создаем основной класс приложения:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

Наконец, мы настраиваем свойства в форматеYAML; так чтоapplication.yml будет нашим файлом конфигурации:

server:
  port: 8761
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false

Here we’re configuring an application port – 8761 is the default one for Eureka servers. Мы говорим встроенномуEureka Client не регистрироваться с «самим собой», потому что наше приложение должно действовать как сервер.

Теперь мы направим наш браузер наhttp://localhost:8761, чтобы просмотреть панель управленияEureka, где мы позже проверим зарегистрированные экземпляры.

На данный момент мы видим основные показатели, такие как состояние и показатели здоровья.

image

3. Клиент Эврики

Чтобы@SpringBootApplication знал об обнаружении, мы должны включить несколькоSpring Discovery Client (например,spring-cloud-starter-netflix-eureka-client) в нашclasspath.

Затем нам нужно аннотировать@Configuration либо@EnableDiscoveryClient, либо@EnableEurekaClient –, обратите внимание, что эта аннотация является необязательной, если у нас есть зависимостьspring-cloud-starter-netflix-eureka-client от пути к классам.

Последний указываетSpring Boot явно использовать Spring Netflix Eureka для обнаружения служб. Чтобы наполнить наше клиентское приложение некоторым образцом жизни, мы также включим пакетspring-boot-starter-web вpom.xml и реализуем контроллерREST.

Но сначала мы добавим зависимости. Опять же, мы можем предоставить зависимостиspring-cloud-starter-parent  определение версий артефактов для нас:


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-starter


    org.springframework.boot
    spring-boot-starter-web

Здесь мы реализуем основной класс приложения:

@SpringBootApplication
@RestController
public class EurekaClientApplication implements GreetingController {

    @Autowired
    @Lazy
    private EurekaClient eurekaClient;

    @Value("${spring.application.name}")
    private String appName;

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

    @Override
    public String greeting() {
        return String.format(
          "Hello from '%s'!", eurekaClient.getApplication(appName).getName());
    }
}

И интерфейсGreetingController:

public interface GreetingController {
    @RequestMapping("/greeting")
    String greeting();
}

Здесь вместо интерфейса мы могли бы просто объявить отображение внутри классаEurekaClientApplication. Интерфейс может быть полезен, если мы хотим поделиться им между сервером и клиентом.

Затем мы должны настроитьapplication.yml с настроенным именем приложенияSpring, чтобы однозначно идентифицировать нашего клиента в списке зарегистрированных приложений.

Мы можем позволитьSpring Boot выбрать для нас случайный порт, потому что позже мы будем обращаться к этой службе по ее имени.

Наконец, мы должны сказать нашему клиенту, где он должен найти реестр:

spring:
  application:
    name: spring-cloud-eureka-client
server:
  port: 0
eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
  instance:
    preferIpAddress: true

Когда мы решили настроить наш клиент Eureka таким образом, мы имели в виду, что этот вид сервиса впоследствии будет легко масштабируемым.

Теперь мы запустим клиент и снова укажем нашему браузеруhttp://localhost:8761, чтобы увидеть его статус регистрации на панели инструментов Eureka. Используя панель инструментов, мы можем выполнить дальнейшую настройку, например, связать домашнюю страницу зарегистрированного клиента с приборной панелью в административных целях. Однако параметры конфигурации выходят за рамки этой статьи.

image

4. Имитировать клиента

Чтобы завершить наш проект с тремя зависимыми микросервисами, мы теперь реализуем веб-приложение, потребляющееREST, используяSpring Netflix Feign Client.

Думайте оFeign как оSpring RestTemplate с возможностью обнаружения, использующем интерфейсы для связи с конечными точками. Эти интерфейсы будут автоматически реализованы во время выполнения, и вместоservice-urls будет использоватьсяservice-names.

БезFeign нам пришлось бы автоматически подключить экземплярEurekaClient к нашему контроллеру, с помощью которого мы могли бы получать служебную информацию отservice-name как объектApplication.

Мы бы использовали этотApplication, чтобы получить список всех экземпляров этой службы, выбрать подходящий и использовать этотInstanceInfo для получения имени хоста и порта. При этом мы могли бы сделать стандартный запрос с любымиhttp client.

Например:

@Autowired
private EurekaClient eurekaClient;

public void doRequest() {
    Application application =
      eurekaClient.getApplication("spring-cloud-eureka-client");
    InstanceInfo instanceInfo = application.getInstances().get(0);
    String hostname = instanceInfo.getHostName();
    int port = instanceInfo.getPort();
    // ...
}

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

Чтобы настроить наш проектFeign Client, мы собираемся добавить следующие четыре зависимости к егоpom.xml:


    org.springframework.cloud
    spring-cloud-starter-feign


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-thymeleaf

Feign Client находится в пакетеspring-cloud-starter-feign. Чтобы включить его, мы должны аннотировать@Configuration с помощью@EnableFeignClients. Чтобы использовать его, мы просто аннотируем интерфейс с помощью@FeignClient(“service-name”) и автоматически подключаем его к контроллеру.

Хороший способ создать такойFeignClients - создать интерфейсы с аннотированными методами@RequestMapping и поместить их в отдельный модуль. Таким образом, они могут быть разделены между сервером и клиентом. На стороне сервера вы можете реализовать их как@Controller, а на стороне клиента они могут быть расширены и аннотированы как@FeignClient.

Кроме того,spring-cloud-starter-eureka package необходимо включить в проект и включить, аннотируя основной класс приложения с помощью@EnableEurekaClient.

Зависимостиspring-boot-starter-web иspring-boot-starter-thymeleaf используются дляpresent a view, содержащего данные, полученные из нашей службыREST.

Это будет наш интерфейсFeign Client:

@FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
    @RequestMapping("/greeting")
    String greeting();
}

Здесь мы реализуем основной класс приложения, который одновременно выступает в качестве контроллера:

@SpringBootApplication
@EnableFeignClients
@Controller
public class FeignClientApplication {
    @Autowired
    private GreetingClient greetingClient;

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

    @RequestMapping("/get-greeting")
    public String greeting(Model model) {
        model.addAttribute("greeting", greetingClient.greeting());
        return "greeting-view";
    }
}

Это будет шаблон HTML для нашего представления:



    
        Greeting Page
    
    
        

По крайней мере, файл конфигурацииapplication.yml почти такой же, как и на предыдущем шаге:

spring:
  application:
    name: spring-cloud-eureka-feign-client
server:
  port: 8080
eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}

Теперь мы можем создать и запустить этот сервис. Наконец, мы укажем нашему браузеруhttp://localhost:8080/get-greeting, и он должен отобразить что-то вроде следующего:

Hello from SPRING-CLOUD-EUREKA-CLIENT!

5. «TransportException: Невозможно выполнить запрос на любом известном сервере»

Во время работы сервера Eureka мы часто сталкиваемся с такими исключениями, как:

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

В основном это происходит из-за неправильной конфигурации вapplication.properties илиapplication.yml. Eureka предоставляет два свойства для клиента, которые можно настраивать.

  • registerWithEureka: Если мы сделаем это свойство какtrue, тогда, пока сервер запускается, встроенный клиент будет пытаться зарегистрироваться на сервере Eureka.

  • fetchRegistry: Встроенный клиент попытается получить реестрEureka, если мы настроим это свойство как истинное.

Теперьwhen we start up the Eureka server, we don’t want to register the inbuilt client to configure itself with the server.

Если мы помечаем указанные выше свойства какtrue (или не настраиваем их какtrue по умолчанию) при запуске сервера, встроенный клиент пытается зарегистрироваться с помощьюEureka сервер, а также пытается получить реестр, который еще не доступен. В результате получаемTransportException.

Поэтому мы никогда не должны настраивать эти свойства какtrue в серверных приложенияхEureka. Правильные настройки, которые следует ввести вapplication.yml, приведены ниже:

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false

6. Заключение

Как мы видели, теперь мы можем реализовать реестр служб, используяSpring Netflix Eureka Server, и зарегистрировать в нем несколькоEureka Clients.

Поскольку нашEureka Client из шага 3 прослушивает случайно выбранный порт, он не знает его местоположение без информации из реестра. С помощьюFeign Client и нашего реестра мы можем найти и использовать службуREST, даже если местоположение изменится.

Наконец, мы получили общую картину использования обнаружения сервисов в микросервисной архитектуре.

Как обычно, вы найдете исходникиon GitHub,, которые также включают набор файлов, связанных сDocker, для использования сdocker-compose для создания контейнеров из нашего проекта.