هذا هو الجزء الثالث من سلسلة من المقالات حول أساسيات هندسة الخدمات المصغرة ، والتي سوف تتعلم فيها كيفية إنشاء خدمة ميكروية لتحويل العملات.
في هذه السلسلة من المقالات ، ستتعرف على مفهوم الخدمات المصغرة وتتعرف على كيفية إنشاء الخدمات المصغرة باستخدام Spring Boot و Spring Cloud.
سيساعدك هذا الدليل على تعلم أساسيات هندسة الخدمات المصغرة. سنبدأ أيضًا في إلقاء نظرة على تطبيق microservice الأساسي باستخدام Spring Boot.
سننشئ زوجًا من الخدمات المصغرة ونجعلهم يتواصلون مع بعضهم البعض باستخدام خوادم اسم Eureka (اسم خادم يوريكا) ورابون لتوازن الحمل على جانب العميل.
هذا المقال جزء من سلسلة Spring Boot Microservices:
سوف تتعلم
- كيفية إنشاء microservice باستخدام Spring التمهيد.
- كيفية استخدام RestTemplate لإنشاء خدمة REST.
- كيفية استخدام Feign لإنشاء خدمة REST.
- فوائد Feign على RestTemplate.
نظرة عامة على الموارد
يمكن لخدمة تحويل العملات (CCS) تحويل العديد من العملات إلى عملة أخرى. يستخدم خدمة فوركس للحصول على قيم صرف العملات الحالية. 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 هو 750،000 INR. يوضح الرسم البياني أدناه العلاقة بين CCS و FS.

هيكل كود المشروع
توضح لقطة الشاشة التالية هيكل المشروع الذي سننشئه.

بعض عناصر المشروع:
- SpringBootMicroserviceCurrencyConversionApplication.java هو فئة تطبيق Spring Boot التي تم إنشاؤها باستخدام Spring Initializer. هذه الفئة بمثابة نقطة انطلاق التطبيق.
- pom.xml - يحتوي على جميع التبعيات اللازمة لإنشاء هذا المشروع. سوف نستخدم Spring Boot Starter Web.
- CurrencyConversionBean.java - الحبة لتخزين الاستجابة التي نريد إرسالها.
- CurrencyExchangeServiceProxy.java - سيكون وكيل Feign للاتصال بخدمة الفوركس.
- CurrencyConversionController.java - جهاز التحكم REST الذي يوفر خدمة تحويل العملات. سوف تستخدم CurrencyExchangeServiceProxy للاتصال بخدمة الفوركس.
الأدوات التي تحتاجها
- مخضرم 3.0+ - أداة البناء
- IDE المفضل لديك. نحن نستخدم الكسوف.
- JDK 1.8+
مشروع جاهز مخضرم مع عينات الكود
يحتوي مستودع جيثب على كل أمثلة الكود.
إنشاء مشروع باستخدام Spring Initializr
إن إنشاء خدمة microservice مع Spring Initializr هو مسيرة سهلة.
Spring Initializr هو أداة رائعة لإنشاء مشاريع Spring Boot بسرعة.
بمساعدة
Spring Initializr ، يمكنك إنشاء مجموعة متنوعة من المشاريع.

يجب اتخاذ الخطوات التالية لإنشاء مشروع تطوير خدمات الويب:
1. قم بتشغيل Spring Initializr واكتب ما يلي:
- اكتب com.in28minutes.springboot.microservice.example.currencyconversion كمجموعة.
- اكتب spring-boot-microservice-currency-conversion باعتباره قطعة أثرية.
- حدد التبعيات التالية: الويب ، DevTools ، Feign
2. انقر فوق
إنشاء مشروع .
3. استيراد المشروع إلى Eclipse: ملف -> استيراد -> مشروع مخضرم موجود.
تذكر قائمة
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 للاتصال بخدمة فوركس ومعالجة الرد. كما ترون ، لإجراء مكالمة خدمة بسيطة ، تحتاج إلى كتابة الكثير من التعليمات البرمجية.
@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 ("/ exchange-exchange / from / {from} / to / {to}") - URI للخدمة التي نود استخدامها
باستخدام وكلاء Feign في وحدة تحكم Microservice
إجراء مكالمة عبر وكيل بسيط جدًا. سترى هذا في العمل في الكود أدناه. كل ما كان علينا فعله هو توصيل الوكيل تلقائيًا واستخدامه للاتصال بالطريقة.
@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); } }
اختبار Microservice باستخدام 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, }
ملخص
أنشأنا اثنين microservices وأقمنا اتصال بينهما.

ومع ذلك ، قمنا بتشفير عنوان URL الثابت لـ FS إلى CCS. هذا يعني أنه عندما يتم تشغيل مثيلات FS جديدة ، فلن تكون لدينا طريقة لتوزيع الحمل بينها. في الجزء التالي ، سنعمل على تمكين موازنة التحميل من جانب العميل باستخدام الشريط.
رمز المثال الكامل/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 /> </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() { } }