基於Spring Cloud和Netflix Discovery的微服務開發
原文鏈接: How to Develop Microservices With Spring Cloud and Netflix Discovery (翻譯:鍾濤)
今天,我將爲大家展示如何使用Eureka發現服務器(discovery server)來搭建一個小型的微服務應用。
我將使用Eureka作爲發現服務器,各個應用可以通過Eureka來發現彼此,建立連接。
對於本例,總共將創建4個微服務應用程序。
- discovery-service - Eureka發現服務器
- library-service - 一個微服務應用程序,同時也是發現客戶端(a discovery client)
- book-service - 一個微服務應用程序,同時也是發現客戶端
- read-service - 一個微服務應用程序,它將同時使用 book-service 和 library-service 。同時也是發現客戶端,它將在發現服務器中註冊自己。
發現服務器將扮演這樣一個角色,所有的微服務應用程序將自己的信息註冊到發現服務器,所有的微服務應用程序也可以訪問這個發現服務器,以獲得其他微服務應用程序的信息。當一個微服務應用程序想訪問另一個微服務應用程序時,它不必提前獲悉對方的主機地址和端口號,它都可以通過詢問發現服務器來獲得,這樣的話,即使對方應用程序的地址發生了改變,也不會造成影響。
當一個應用程序從一臺物理服務器遷移到另一臺新的物理服務器時,我們可以從發現服務器知道新的主機地址和端口。假設您決定將應用程序從印度服務器( http://myservice.gov.in:9001 )遷移到美國服務器( http://myservice.gov.us:99013 ),您不需要通知之前使用您服務的任何應用程序。他們可以從發現服務器自動知道新的主機地址和端口號,甚至不需要做任何事情。
請參見下圖以瞭解發現服務器是如何工作的,如何爲註冊的發現客戶端提供服務。例如, read-service 需要使用 book-service 和 library-service 提供的服務,那麼 read-service 如何獲得對方的主機名和端口號呢?這些信息將由 discovery-service 提供,因爲 book-service 和 library-service 已經將信息註冊到了 discovery-service 中。
要了解更多關於Spring cloud Netflix的信息,您可以訪問 https://cloud.spring.io/spring ... .html 。
下面,讓我們一步一步地開發這個項目。
步驟1
首先,我們將創建一個基於Eureka的 discovery-service 。如果您是Spring Boot的新手,可以閱讀我的文章 https://github.com/prateekpara ... rest2 來創建一個Spring Boot應用程序。現在,請點擊 https://start.spring.io/ 打開Spring Initializr。現在請按照下方截圖操作。
單擊 ADD DEPENDENCIES 按鈕並選擇需要的依賴項(在搜索欄中只需鍵入依賴項——Eureka和Actuator即可完成添加。不要選錯了,不要選擇Eureka client)
現在單擊 GENERATE 按鈕生成項目,並將其保存到您的機器上,作爲maven項目導入到您的工具中(這裏我使用的是Eclipse)。
現在,打開 DemoDiscoveryServerApplication.java ,並添加 @EnableEurekaServer
:
```java
package com.bhaiti.jorhat.demodiscoveryserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableEurekaServer
public class DemoDiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoDiscoveryServerApplication.class, args);
}
}
```
將 application.properties 重命名爲 application.yml ,並添加如下信息:
yaml server.port: 9001 spring.application.name: demo-discovery-server eureka: server: evictionIntervalTimerInMs: 3000 response-cache-update-interval-ms: 3000 client: registerWithEureka: false fetchRegistry: false service-url.defaultZone: http://localhost:${server.port}/eureka
從上面的配置信息中,可以看到, registerWithEureka 和 fetchRegistry 的值都是 false 。原因是我們不希望註冊這個應用程序本身,因爲此應用程序將作爲發現服務器,接收其他應用程序的註冊。有關配置的詳細信息,請參考 repository 。
您的發現服務器已經準備好了。
在項目主目錄中,執行以下命令編譯應用程序:
mvn clean package
啓動應用程序:
java -jar target/demo-discovery-server-0.0.1-SNAPSHOT.jar
現在您可以通過儀表板來查看Eureka發現服務器,請點擊 http://localhost:9001
現在你還看不到任何Eureka客戶端應用程序。讓我們開發我們的第一個Eureka客戶端應用程序 book-service 。
步驟2
按以下步驟創建一個REST應用程序 book-service
請注意,這次我們選擇了 Eureka Client 作爲依賴項 ,因爲我們的REST應用程序也是Eureka客戶端應用程序。生成項目並將其作爲maven項目導入到eclipse中。
將 application.properties 重命名爲 application.yml ,並添加如下配置:
yaml server.port: 9901 spring: application.name: book-service eureka: client: serviceUrl: defaultZone: http://localhost:9001/eureka/ registryFetchIntervalSeconds: 1 instance: leaseRenewalIntervalInSeconds: 1
通過配置項 defaultZone 可以看到,這個Eureka客戶端應用程序將自己註冊到 http://localhost:9001/eureka/ 這個地址。現在我們必須在REST應用程序 book-service 中進行一些編碼。首先打開 BookServiceApplication.java 文件,並在其中添加 @EnableDiscoveryClient
以激活發現客戶機。
```java
package com.bhaiti.jorhat.book.bookservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class BookServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BookServiceApplication.class, args);
}
}
```
按如下所示,創建一個新的java類 BookService.java
並添加如下代碼:
```java
package com.bhaiti.jorhat.book.bookservice;
import java.util.Arrays;
import java.util.List;
public class BookService {
private static List<String> bookList = Arrays.asList("Book1","Book2","Book3");
public static List<String> getBookList() {
return bookList;
}
}
```
同樣的方法,創建 BookController.java
```java
package com.bhaiti.jorhat.book.bookservice;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BookController {
@GetMapping("/books")
public ResponseEntity<List<String>> getBookList(){
return ResponseEntity.ok(BookService.getBookList());
}
}
```
在 pom.xml
中添加如下依賴項:
xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
現在,我們可以編譯並且運行它了:
shell cd book-service mvn clean package java -jar target/book-service-0.0.1-SNAPSHOT.jar
現在刷新Eureka(發現服務器)儀表板,您可以看到 book-service 已經被註冊進來了。
步驟3
現在創建 library-service 應用程序。只需重複步驟2,創建項目並將其導入到eclipse中。
參考 book-service 更新 library-service 的 pom .xml
。分別添加兩個類 LibraryService.java 和 LibraryController.java
@EnableDiscoveryClient
java @SpringBootApplication @EnableDiscoveryClient public class LibraryServiceApplication { public static void main(String[] args) { SpringApplication.run(LibraryServiceApplication.class, args); } }
按如下方式創建 LibraryService.java
```java
package com.bhaiti.uk.global.repo;
import java.util.HashMap;
import java.util.Map;
public class LibraryService {
private static Map<String, String> libList;
static {
libList = new HashMap<String, String>();
libList.put("Book1", "Library3");
libList.put("Book2", "Library1");
libList.put("Book3", "Library2");
}
public static Map<String, String> getLibList() {
return libList;
}
}
```
按如下方式創建 LibraryController.java
```java
package com.bhaiti.uk.global.repo;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LibraryController {
@GetMapping("/librarys")
public ResponseEntity<Map<String, String>> getBookList(){
return ResponseEntity.ok(LibraryService.getLibList());
}
}
```
將 application.properties 重命名爲 application.yml ,並添加如下配置:
yaml server.port: 9902 spring: application.name: library-service eureka: client: serviceUrl: defaultZone: http://localhost:9001/eureka/ registryFetchIntervalSeconds: 1 instance: leaseRenewalIntervalInSeconds: 1
編譯並且運行應用程序:
shell cd library-service mvn clean package java -jar target/library-service-0.0.1-SNAPSHOT.jar
現在刷新Eureka(發現服務器)儀表板,您可以看到 library-service 已經被註冊進來了。
步驟5
現在我們將創建最後一個REST應用程序 - read-service 。創建並將其導入到eclipse中。請注意,我們在這裏增加了一個依賴項,即OpenFeign。
將 application.properties 重命名爲 application.yml ,並添加如下配置:
yaml server.port: 9903 spring: application.name: library-service eureka: client: serviceUrl: defaultZone: ${EUREKA_URI:http://localhost:9001/eureka} registryFetchIntervalSeconds: 1 instance: leaseRenewalIntervalInSeconds: 1
參照 library-service 修改 pom.xml
。
在 read-service 中,我們將同時使用 book-service 和 library-service .。爲了調用 book-service 和 library-service 的REST API,我們將在這裏實現一個假想客戶機。
首先修改 ReadServiceApplication.java :
java @SpringBootApplication @EnableDiscoveryClient public class ReadServiceApplication {
現在,創建我們的Feign客戶端。分別創建兩個接口 BookClient.java 和 LibraryClient 。
```java
package com.bhaiti.jorhat.read;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("book-service")
public interface BookClient {
@GetMapping("/books")
List<String> getBookList();
}
```
```java
package com.bhaiti.jorhat.read;
import java.util.Map;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("library-service")
public interface LibraryClient {
@GetMapping("/librarys")
Map<String, String> getLibraryList();
}
```
使用FeignClient的好處是,當進行REST調用時,您不需要知道對方的主機名和端口號。在這裏,我們沒有使用URI來對 book-service 進行REST調用。Feign可以獲取REST調用所需的一切,從 discovery server 獲取關於 book-service 和 library-service 的一切信息(主機名和端口號)。因爲 book-service 和 library-service 不僅是基於REST的應用程序,也是Eureka客戶端應用程序,因此它可以從發現服務器中獲取的其他Eureka客戶端應用程序的信息。
要了解更多關於FeignClient的信息,請訪問 https://cloud.spring.io/spring ... .html 和 https://cloud.spring.io/spring ... html/
假設您不想使用FeignClient,而想使用http連接或 RestTemplate
進行REST調用,在這種情況下,您可以使用以下代碼獲取應用程序的主機名和端口號。
```java
@Autowired
private EurekaClient eurekaClient;
public String getBaseUrl() {
Application application = eurekaClient.getApplication("book-service");
InstanceInfo instanceInfo = application.getInstances().get(0);
String hostname = instanceInfo.getHostName();
int port = instanceInfo.getPort();
return " http://" + hostname + ":" + port;
}
```
按如下方式創建 ReadServiceController.java
```java
package com.bhaiti.jorhat.read;
import java.util.List;
import java.util.Map;
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;
@RestController
public class ReadServiceController {
@Autowired
BookClient bookClient;
@Autowired
LibraryClient libraryClient;
@GetMapping(path= "/read/{bookName}", produces = "application/json")
public ResponseEntity<String> getReadingLocation(@PathVariable(value = "bookName") String bookName){
String response;
List<String> bookList = bookClient.getBookList();
if(bookList.contains(bookName)) {
Map<String, String> libList = libraryClient.getLibraryList();
response = "You can read this book - " + bookName
+ " at this Library - " + libList.get(bookName);
} else {
response = "Your Book - " + bookName + " is not currently available in Libaries";
}
return ResponseEntity.ok().body(response);
}
}
```
最後,按如下方式修改 ReadServiceApplication.java
```java
package com.bhaiti.jorhat.read;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class ReadServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ReadServiceApplication.class, args);
}
}
```
現在,您的微服務應用程序已經完全準備好進行測試了。
首先編譯並運行它,然後檢查Eureka服務器。
shell cd read-service mvn clean package java -jar target/read-service-0.0.1-SNAPSHOT.jar
現在,點擊下面的URL並檢查
您將在瀏覽器中看到如下信息。
只需將書名更改爲Book1、Book2和Book4,並對每個條目進行測試。您可以通過以下鏈接獲得所有源代碼 - https://github.com/prateekpara ... ample 。
希望你喜歡本教程。