Микросервисы со Spring Boot. Часть 3. Создание микросервиса конвертации валют

от автора

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

В этой серии статей вы познакомитесь с концепцией микросервисов и узнаете, как создавать микросервисы с помощью Spring Boot и Spring Cloud.

Это руководство поможет вам изучить основы микросервисных архитектур. Мы также начнем рассматривать базовую реализацию микросервиса со Spring Boot.

Мы создадим пару микросервисов и заставим их общаться друг с другом с помощью сервера имен Eureka (Eureka Naming Server) и Ribbon для балансировки нагрузки на стороне клиента.

Это статья входит в серию статей «Микросервисы со Spring Boot»:

Вы изучите

  • Как создать микросервис с помощью Spring Boot.
  • Как использовать RestTemplate для создания REST сервиса.
  • Как использовать Feign для создания REST сервиса.
  • Преимущества Feign перед RestTemplate.

Обзор ресурсов

Сервис конвертации валют (CCS) может конвертировать множество валют в другую валюту. Он использует Forex сервис для получения текущих значений обмена валюты. CCS является потребителем услуг.

Пример запроса и ответа показан ниже:

GET to http://localhost:8100/currency-converter/from/EUR/to/INR/quantity/10000

{   id: 10002,   from: "EUR",   to: "INR",   conversionMultiple: 75,   quantity: 10000,   totalCalculatedAmount: 750000,   port: 8000, }

Запрос выше позволяет определить стоимость 10000 евро в индийских рупиях.
TotalCalculatedAmount составляет 750000 INR. Диаграмма ниже показывает связь между CCS и FS.

Структура кода проекта

На следующем скриншоте показана структура проекта, который мы создадим.

Некоторые элементы проекта:

  • SpringBootMicroserviceCurrencyConversionApplication.java — класс приложения Spring Boot, созданный с помощью Spring Initializer. Этот класс действует как точка запуска приложения.
  • pom.xml — содержит все зависимости, необходимые для создания этого проекта. Мы будем использовать Spring Boot Starter Web.
  • CurrencyConversionBean.java — Бин для хранения ответа, который мы хотим отправить.
  • CurrencyExchangeServiceProxy.java — это будет Feign Proxy для вызова сервиса Forex.
  • CurrencyConversionController.java — Spring REST контроллер, предоставляющий сервис конвертации валют. Он будет использовать CurrencyExchangeServiceProxy для вызова сервиса Forex.

Инструменты, которые вам понадобятся

  • Maven 3.0+ — инструмент для сборки
  • Ваш любимый IDE. Мы используем Eclipse.
  • JDK 1.8+

Готовый проект Maven с примерами кода

В Github репозитории есть все примеры кода.

Создание проекта с помощью Spring Initializr

Создание микросервиса с Spring Initializr — это легкая прогулка.

Spring Initializr— отличный инструмент для быстрого создания ваших проектов Spring Boot.

С помощью Spring Initializr вы можете создавать самые разные проекты.

Следующие шаги нужно сделать для создания проекта разработки веб-сервисов:

1. Запустите Spring Initializr и наберите следующее:

  • Наберите com.in28minutes.springboot.microservice.example.currencyconversion в качестве группы.
  • Наберите в качестве артефакта spring-boot-microservice-currency-conversion.
  • Выберите следующие зависимости: Web, DevTools, Feign

2. Нажмите Generate Project.

3. Импортируйте проект в Eclipse: File -> Import -> Existing Maven Project.

Не забудьте указать Feign в зависимостях.

Создание CurrencyConversionBean

Это простой бин для создания ответа.

public class CurrencyConversionBean {   private Long id;   private String from;   private String to;   private BigDecimal conversionMultiple;   private BigDecimal quantity;   private BigDecimal totalCalculatedAmount;   private int port;   public CurrencyConversionBean() {   }   public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,       BigDecimal totalCalculatedAmount, int port) {     super();     this.id = id;     this.from = from;     this.to = to;     this.conversionMultiple = conversionMultiple;     this.quantity = quantity;     this.totalCalculatedAmount = totalCalculatedAmount;     this.port = port;   }

Реализация REST-клиента с RestTemplate

Приведенный ниже код демонстрирует реализацию REST клиента для вызова сервиса Forex и обработки ответа. Как видите, для выполнения простого вызова службы нужно написать много кода.

@RestController public class CurrencyConversionController {   private Logger logger = LoggerFactory.getLogger(this.getClass());   @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")   public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,       @PathVariable BigDecimal quantity) {     Map<String, String> uriVariables = new HashMap<>();     uriVariables.put("from", from);     uriVariables.put("to", to);     ResponseEntity<CurrencyConversionBean> responseEntity = new RestTemplate().getForEntity(         "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class,         uriVariables);     CurrencyConversionBean response = responseEntity.getBody();     return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,         quantity.multiply(response.getConversionMultiple()), response.getPort());   }

Настройка имени приложения и порта

/spring-boot-microservice-currency-conversion-service/src/main/resources/application.properties

spring.application.name=currency-conversion-service server.port=8100

Тестирование микросервиса

Запустите Spring Boot приложение, запустив SpringBootMicroserviceCurrencyConversionApplication.java

GET to http://localhost:8100/currency-converter/from/EUR/to/INR/quantity/10000

{   id: 10002,   from: "EUR",   to: "INR",   conversionMultiple: 75,   quantity: 10000,   totalCalculatedAmount: 750000,   port: 8000, }

Создание Feign прокси

Feign предоставляет лучшую альтернативу RestTemplate для вызова REST API.

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyExchangeServiceProxy.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable;  @FeignClient(name="forex-service" url="localhost:8000") public interface CurrencyExchangeServiceProxy {   @GetMapping("/currency-exchange/from/{from}/to/{to}")   public CurrencyConversionBean retrieveExchangeValue     (@PathVariable("from") String from, @PathVariable("to") String to); }

Сначала мы определим простой прокси:

  • @FeignClient(name=«forex-service» url=«localhost:8100») — объявляет, что это Feign клиент, а URL-адрес, на котором имеется Forex сервис, является localhost: 8100
  • @GetMapping("/currency-exchange/from/{from}/to/{to}") — URI службы, которую мы хотели бы использовать

Использование Feign прокси в контроллере микросервиса

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

@Autowired   private CurrencyExchangeServiceProxy proxy;   @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}")   public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to,       @PathVariable BigDecimal quantity) {     CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to);     logger.info("{}", response);     return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,         quantity.multiply(response.getConversionMultiple()), response.getPort());   }

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

Прежде чем мы сможем использовать Feign, нам нужно включить его с помощью аннотации @EnableFeignClients в соответствующем пакете, где определены клиентские прокси.

@SpringBootApplication @EnableFeignClients("com.in28minutes.springboot.microservice.example.currencyconversion") @EnableDiscoveryClient public class SpringBootMicroserviceCurrencyConversionApplication {   public static void main(String[] args) {     SpringApplication.run(SpringBootMicroserviceCurrencyConversionApplication.class, args);   } }

Тестирование микросервиса с использованием Feign

GET to http://localhost:8100/currency-converter-feign/from/EUR/to/INR/quantity/10000
{   id: 10002,   from: "EUR",   to: "INR",   conversionMultiple: 75,   quantity: 10000,   totalCalculatedAmount: 750000,   port: 8000, }

Резюме

Мы создали два микросервиса и установили связь между ними.

Тем не менее, мы жестко запрограммировали URL для FS в CCS. Это означает, что когда запускаются новые экземпляры FS, у нас нет возможности распределить нагрузку между ними. В следующей части мы включим распределение нагрузки на стороне клиента с помощью Ribbon.

Полный код примера

/spring-boot-microservice-currency-conversion-service/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">   <modelVersion>4.0.0</modelVersion>   <groupId>com.in28minutes.springboot.microservice.example.currency-conversion</groupId>   <artifactId>spring-boot-microservice-currency-conversion</artifactId>   <version>0.0.1-SNAPSHOT</version>   <packaging>jar</packaging>   <name>spring-boot-microservice-currency-conversion</name>   <description>Microservices with Spring Boot and Spring Cloud - Currency Conversion Service</description>   <parent>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-parent</artifactId>     <version>2.0.0.M3</version>     <relativePath /> <!-- lookup parent from repository -->   </parent>   <properties>     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>     <java.version>1.8</java.version>     <spring-cloud.version>Finchley.M2</spring-cloud.version>   </properties>   <dependencies>     <dependency>       <groupId>org.springframework.boot</groupId>       <artifactId>spring-boot-starter-web</artifactId>     </dependency>     <dependency>       <groupId>org.springframework.cloud</groupId>       <artifactId>spring-cloud-starter-feign</artifactId>     </dependency>     <dependency>       <groupId>org.springframework.boot</groupId>       <artifactId>spring-boot-devtools</artifactId>       <scope>runtime</scope>     </dependency>     <dependency>       <groupId>org.springframework.boot</groupId>       <artifactId>spring-boot-starter-test</artifactId>       <scope>test</scope>     </dependency>   </dependencies>   <dependencyManagement>     <dependencies>       <dependency>         <groupId>org.springframework.cloud</groupId>         <artifactId>spring-cloud-dependencies</artifactId>         <version>${spring-cloud.version}</version>         <type>pom</type>         <scope>import</scope>       </dependency>     </dependencies>   </dependencyManagement>   <build>     <plugins>       <plugin>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-maven-plugin</artifactId>       </plugin>     </plugins>   </build>   <repositories>     <repository>       <id>spring-snapshots</id>       <name>Spring Snapshots</name>       <url>https://repo.spring.io/snapshot</url>       <snapshots>         <enabled>true</enabled>       </snapshots>     </repository>     <repository>       <id>spring-milestones</id>       <name>Spring Milestones</name>       <url>https://repo.spring.io/milestone</url>       <snapshots>         <enabled>false</enabled>       </snapshots>     </repository>   </repositories>   <pluginRepositories>     <pluginRepository>       <id>spring-snapshots</id>       <name>Spring Snapshots</name>       <url>https://repo.spring.io/snapshot</url>       <snapshots>         <enabled>true</enabled>       </snapshots>     </pluginRepository>     <pluginRepository>       <id>spring-milestones</id>       <name>Spring Milestones</name>       <url>https://repo.spring.io/milestone</url>       <snapshots>         <enabled>false</enabled>       </snapshots>     </pluginRepository>   </pluginRepositories> </project>

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyConversionBean.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import java.math.BigDecimal;  public class CurrencyConversionBean {   private Long id;   private String from;   private String to;   private BigDecimal conversionMultiple;   private BigDecimal quantity;   private BigDecimal totalCalculatedAmount;   private int port;   public CurrencyConversionBean() {   }   public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,       BigDecimal totalCalculatedAmount, int port) {     super();     this.id = id;     this.from = from;     this.to = to;     this.conversionMultiple = conversionMultiple;     this.quantity = quantity;     this.totalCalculatedAmount = totalCalculatedAmount;     this.port = port;   }   public Long getId() {     return id;   }   public void setId(Long id) {     this.id = id;   }   public String getFrom() {     return from;   }   public void setFrom(String from) {     this.from = from;   }   public String getTo() {     return to;   }   public void setTo(String to) {     this.to = to;   }   public BigDecimal getConversionMultiple() {     return conversionMultiple;   }   public void setConversionMultiple(BigDecimal conversionMultiple) {     this.conversionMultiple = conversionMultiple;   }   public BigDecimal getQuantity() {     return quantity;   }   public void setQuantity(BigDecimal quantity) {     this.quantity = quantity;   }   public BigDecimal getTotalCalculatedAmount() {     return totalCalculatedAmount;   }   public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) {     this.totalCalculatedAmount = totalCalculatedAmount;   }   public int getPort() {     return port;   }   public void setPort(int port) {     this.port = port;   } }

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyConversionController.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;  @RestController public class CurrencyConversionController {   private Logger logger = LoggerFactory.getLogger(this.getClass());   @Autowired   private CurrencyExchangeServiceProxy proxy;   @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")   public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,       @PathVariable BigDecimal quantity) {     Map<String, String> uriVariables = new HashMap<>();     uriVariables.put("from", from);     uriVariables.put("to", to);     ResponseEntity<CurrencyConversionBean> responseEntity = new RestTemplate().getForEntity(         "http://localhost:8000/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class,         uriVariables);     CurrencyConversionBean response = responseEntity.getBody();     return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,         quantity.multiply(response.getConversionMultiple()), response.getPort());   }   @GetMapping("/currency-converter-feign/from/{from}/to/{to}/quantity/{quantity}")   public CurrencyConversionBean convertCurrencyFeign(@PathVariable String from, @PathVariable String to,       @PathVariable BigDecimal quantity) {     CurrencyConversionBean response = proxy.retrieveExchangeValue(from, to);     logger.info("{}", response);     return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,         quantity.multiply(response.getConversionMultiple()), response.getPort());   } }

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/CurrencyExchangeServiceProxy.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable;  @FeignClient(name="forex-service" url="localhost:8000") public interface CurrencyExchangeServiceProxy {   @GetMapping("/currency-exchange/from/{from}/to/{to}")   public CurrencyConversionBean retrieveExchangeValue     (@PathVariable("from") String from, @PathVariable("to") String to); }

/spring-boot-microservice-currency-conversion-service/src/main/java/com/in28minutes/springboot/microservice/example/currencyconversion/SpringBootMicroserviceCurrencyConversionApplication.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients;  @SpringBootApplication @EnableFeignClients("com.in28minutes.springboot.microservice.example.currencyconversion") public class SpringBootMicroserviceCurrencyConversionApplication {   public static void main(String[] args) {     SpringApplication.run(SpringBootMicroserviceCurrencyConversionApplication.class, args);   } } 

/spring-boot-microservice-currency-conversion-service/src/main/resources/application.properties

spring.application.name=currency-conversion-service server.port=8100

/spring-boot-microservice-currency-conversion-service/src/test/java/com/in28minutes/springboot/microservice/example/currencyconversion/SpringBootMicroserviceCurrencyConversionApplicationTests.java

package com.in28minutes.springboot.microservice.example.currencyconversion;  import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;  @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootMicroserviceCurrencyConversionApplicationTests {   @Test   public void contextLoads() {   } }

ссылка на оригинал статьи https://habr.com/ru/post/485094/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *