Статьи

Создание собственных приложений для облачной среды в Spring: часть 2

В  части 1  этого урока, я говорил о некоторых особенностях Spring Cloud , и мы начали строить приложение microservice , который будет отображать список препятствий гонок. В конце первой части у нас было три сервиса / приложения, одно из которых обслуживало данные гонки, другое — данные участника гонки, а последнее — наше веб-приложение. Мы закончили первую часть, когда столкнулись с проблемой междоменных доменов, когда пытались сделать запрос к нашей службе гонок из нашего веб-сервиса.

Как я уже упоминал, существует несколько способов решения междоменной проблемы, таких как использование CORS, но это решение плохо масштабируется в архитектуре на основе микросервисов. Spring Cloud Netflix имеет два проекта, которые могут помочь решить эту проблему простым способом, который поддерживает микросервисные архитектуры. Первый проект, Eureka, позволит нам настроить обнаружение служб для всех служб в нашем приложении для микросервисов. Эврика имеет как серверные, так и клиентские компоненты. Сервер Eureka — это то, что регистрируют все клиенты, и где хранится список доступных служб и где они расположены (их URL). Клиентский компонент Eureka — это то, что мы будем интегрировать в каждый из наших микросервисов.

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

Настройка сервера Eureka

Перейдите на  start.spring.io  и заполните форму, следуя снимку экрана ниже.

Снимок экрана 2015-09-10 в 14.10.52

Нажмите кнопку «Создать», чтобы загрузить исходный код, а затем импортируйте новый проект в свою среду IDE. Если вы откроете файл POM для этого нового проекта, вы заметите следующую зависимость

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

Мы впервые видим зависимость от Spring Cloud. Он работает так же, как и другие «стартовые» зависимости для Spring Boot. Управление версиями осуществляется родительским элементом Spring Cloud, который вы также найдете в разделе управления зависимостями POM.

Чтобы заставить это приложение Spring Boot выступать в качестве сервера Eureka, все, что нам нужно сделать, — это добавить одну аннотацию к нашему классу приложения и добавить пару свойств в файл свойств нашего приложения / YAML-файл. Откройте  OcrEurekaApplication.java  в com.ryanjbaxter.spring.cloud.ocr.eureka . В верхней части файла класса, выше или ниже @SpringBootApplication,  добавьте  @EnableEurekaServer . Ваш файл класса должен выглядеть следующим образом.

package com.ryanjbaxter.spring.cloud.ocr.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class OcrEurekaApplication {

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

И это все, никакого кода для написания вообще!

Теперь перейдите в  src / main / resources  и переименуйте  application.properties  в  application.yml  и откройте файл  application.yml . Добавьте следующие свойства в ваш файл YAML

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

Все в разделе eureka файла YAML является технически необязательным, но пока устраняет некоторые ненужные шумы в файлах журнала. Eureka «из коробки» настроена на высокую доступность, поэтому ожидается, что будет второй сервер Eureka, с которым можно будет реплицировать информацию. Поскольку сейчас мы работаем только локально, нам не нужно об этом беспокоиться, поэтому эти свойства просто отключают эту репликацию. Если вы не добавите эти свойства, все будет работать нормально, но вы увидите некоторые ошибки в журналах.

Чтобы запустить наш сервер Eureka, просто запустите приложение Spring Boot. Как только приложение запустится, перейдите по адресу http: // localhost: 8761,  и вы увидите красивую панель управления Eureka, в которой перечислены все службы, зарегистрированные в Eureka. В настоящее время их нет, так что давайте исправим это.

Включение клиентов Eureka

Давайте настроим наши сервисы, чтобы они стали клиентами Eureka. Сначала нам нужно назвать наши услуги. По умолчанию Spring Cloud Netflix будет использовать имя приложения в качестве имени службы при регистрации служб в Eureka. Чтобы дать имена нашему приложению, мы можем установить определенное свойство Spring Boot. В   папке рас, участников и веб-сервисов src / main / resources создайте файл с именем bootstrap.yml . В   файлах bootstrap.yml добавьте следующие свойства.

spring:
  application:
    name: web

Приведенный выше фрагмент кода представляет собой пример   файла bootstrap.yml из веб-службы (мы даем приложению имя web). В файлах bootstrap.yml для сервисов рас и участников измените  свойство name на  расы  и  участников  соответственно.

Теперь, когда у наших сервисов есть имена, давайте добавим к ним клиентские зависимости Eureka. В файлах POM для рас, участников и веб-сервисов добавьте следующий раздел управления зависимостями

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Кроме того, вы захотите добавить следующую зависимость для всех трех POM

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

Это заботится о наших зависимостях, теперь мы можем сделать каждый сервис клиентом, добавив одну аннотацию в файл класса приложения и добавив некоторые свойства в файл свойств приложения. Откройте файл класса приложения для каждой службы и добавьте  @EnableEurekaClient  в файл класса. Например, вот что представляет собой файл класса приложения для веб-службы

package com.ryanjbaxter.spring.cloud.ocr.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 

@SpringBootApplication 
@EnableDiscoveryClient
public class OcrWebApplication {

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

Теперь откройте файл application.yml для каждого сервиса и добавьте следующие свойства

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

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

Запустите все приложения, сервер Eureka, сервис гонок, сервис участников и веб-сервис. Всем службам требуется несколько минут, чтобы зарегистрироваться в Eureka. Если вы смотрите журналы, вы должны увидеть, что регистрация происходит. Например, вот журналы из сервиса гонок, когда он регистрируется в Eureka.

2015-09-10 10:21:56.762  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Disable delta property : false
2015-09-10 10:21:56.763  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Single vip registry refresh property : null
2015-09-10 10:21:56.763  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Force full registry fetch : false
2015-09-10 10:21:56.763  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Application is null : false
2015-09-10 10:21:56.763  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Registered Applications size is zero : true
2015-09-10 10:21:56.763  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Application version is -1: false
2015-09-10 10:21:56.768  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : Getting all instance registry info from the eureka server
2015-09-10 10:21:56.769  INFO 5149 --- [pool-3-thread-1] com.netflix.discovery.DiscoveryClient    : The response status is 200
2015-09-10 10:21:56.851  INFO 5149 --- [pool-2-thread-1] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local - Re-registering apps/RACES
2015-09-10 10:21:56.851  INFO 5149 --- [pool-2-thread-1] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local: registering service...
2015-09-10 10:21:56.885  INFO 5149 --- [pool-2-thread-1] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local - registration status: 204
2015-09-10 10:22:06.770  INFO 5149 --- [scoveryClient-2] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local - retransmit instance info with status UP
2015-09-10 10:22:06.770  INFO 5149 --- [scoveryClient-2] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local: registering service...
2015-09-10 10:22:06.779  INFO 5149 --- [scoveryClient-2] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_RACES/ryans-macbook-pro.local - registration status: 204

Если вы видите это в журналах ваших услуг, значит, все работает. Как только вы начнете просматривать эти журналы, вы можете перейти на  http: // localhost: 8671  и проверить панель инструментов Eureka. Вы должны увидеть что-то похожее на скриншот ниже со всеми зарегистрированными сервисами.

Снимок экрана 2015-09-10 в 2.44.18 вечера

Настройка обратного прокси с Zuul

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

Для начала нам нужно добавить зависимость Zuul Starter в POM нашего веб-сервиса. Откройте файл POM и добавьте следующую зависимость.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

Снова включить Zuul в нашем приложении так же просто, как добавить еще одну аннотацию в наш файл класса приложения и добавить некоторые свойства в файл свойств нашего приложения. Откройте OcrWebApplication.java  в  com.ryanjbaxter.spring.cloud.ocr.web  и добавьте  @EnableZuulProxy  в файл класса.

package com.ryanjbaxter.spring.cloud.ocr.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class OcrWebApplication {

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

Теперь откройте  application.yml  для веб-сервиса и добавьте следующие свойства

zuul:
  routes:
    races: /races/**
    participants: /paticipants/**

По умолчанию Zuul будет пересылать запросы на путь xyz в службу xzy. Например, если вы отправите запрос на http: // localhost: 8080 / races, он перенаправит этот запрос в службу гонок и вызовет http: // localhost: 8282 /. Однако, если вы сделаете запрос к http: // localhost: 8080 / races / 123, он не будет знать, что с ним делать, потому что не знает о дополнительной информации о пути. В свойствах выше мы просто говорим Zuul пересылать все запросы к / races / ** службе гонок и все запросы к / участники / ** службе участников.

После внесения вышеуказанных изменений в веб-сервис перезапустите приложение. Как только он перерегистрируется в Eureka, он пытается использовать обратный прокси-сервер для прокси-запросов к сервисам. Например, вы должны иметь возможность открыть браузер и перейти по  адресу http: // localhost: 8080 / races  и получить обратно массив информации о гонке. Он должен выглядеть точно так же, как если бы вы обратились к службе напрямую, перейдя по  адресу http: // localhost: 8282 . Точно так же вы сможете перейти на http: // localhost: 8080 / members  и получить список участников. Если они работают, то все настроено правильно, и вы готовы к работе. Теперь мы можем использовать обратный прокси-сервер и Eureka для завершения реализации нашего веб-приложения.