Spring Cloud Netflix Eureka介紹

1.概述

在本教程中,我們將通過“ Spring Cloud Netflix Eureka ”介紹client-side service發現。

Client-side service discovery使服務無需硬編碼主機名和端口即可相互查找和通信。這種體系結構中唯一的“固定點”由service registry組成,每個服務都必須向該service registry進行註冊。

缺點是所有客戶端都必須實現某種邏輯才能與此固定點進行交互。假設在實際請求之前進行了額外的網絡往返。

使用Netflix Eureka,每個客戶端可以同時充當服務器,以將其狀態復製到連接的對等方。換句話說,客戶端檢索service registry的所有已連接對等方的列表,並通過負載平衡算法向所有其他服務發出所有其他請求。

要獲知客戶端的存在,他們必須向註冊表發送心跳信號。

為了實現本文的目標,我們將實現三個microservices

  • service registry**Eureka Server** ),
  • 在註冊表( **Eureka Client** )上註冊的REST服務和
  • 一個Web應用程序,它將REST服務用作支持註冊表的客戶端( Spring Cloud Netflix **Feign Client** )。

2. Eureka服務器

實施Eureka Server進行服務註冊非常簡單:

  1. [spring-cloud-starter-netflix-eureka-server](https://search.maven.org/search?q=spring-cloud-starter-netflix-eureka-server)到依賴項
  2. 通過使用@EnableEurekaServer註釋在@SpringBootApplication啟用Eureka服務器
  3. 配置一些屬性

但是,我們將逐步進行。

首先,我們將創建一個新的Maven項目並將依賴項放入其中。您必須注意,我們正在將[spring-cloud-starter-parent](https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.cloud%22%20AND%20a%3A%22spring-cloud-starter-parent%22)導入到本教程中描述的所有項目中:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>

 </dependency>



 <dependencyManagement>

 <dependencies>

 <dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-parent</artifactId>

 <version>Greenwich.RELEASE</version>

 <type>pom</type>

 <scope>import</scope>

 </dependency>

 </dependencies>

 </dependencyManagement>

注意:我們可以在Spring的Projects文檔中查看最新的Spring Cloud版本。

接下來,我們將創建主應用程序類:

@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

在這裡,我們正在配置一個應用程序端口– Eureka服務器的默認端口是8761我們告訴內置的Eureka Client不要向“自己”註冊,因為我們的應用程序應充當服務器。

現在,將瀏覽器指向http:// localhost:8761,以查看Eureka儀表板,稍後我們將在其中檢查註冊的實例。

目前,我們看到諸如狀態和健康指標之類的基本指標。

Spring

3. Eureka客戶端

為了使@SpringBootApplication能夠發現,我們必須在classpath.包含一些Spring Discovery Client (例如spring-cloud-starter-netflix-eureka-clientclasspath.

然後,我們需要使用@EnableDiscoveryClient@EnableEurekaClient –註釋@Configuration @EnableEurekaClient –注意,如果我們對類路徑具有spring-cloud-starter-netflix-eureka-client依賴性,則此註釋是可選的。

後者告訴Spring Boot明確使用Spring Netflix Eureka進行服務發現。為了使我們的客戶端應用程序具有一些示例壽命,我們還將在pom.xml包含spring-boot-starter-web包,並實現REST控制器。

但是首先,我們將添加依賴項。同樣,我們可以將其留給spring-cloud-starter-parent依賴項來為我們找出工件版本:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-netflix-eureka-starter</artifactId>

 </dependency>

 <dependency>

 <groupId>org.springframework.boot</groupId>

 <artifactId>spring-boot-starter-web</artifactId>

 </dependency>

在這裡,我們將實現主要的應用程序類:

@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類內部簡單地聲明映射。如果我們要在服務器和客戶端之間共享該接口,則該接口可能很有用。

接下來,我們必須使用配置Spring應用程序名稱來設置application.yml ,以在註冊的應用程序列表中唯一標識我們的客戶端。

我們可以讓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 Client時,我們牢記這種服務以後應該可以輕鬆擴展。

現在,我們將運行客戶端,並將瀏覽器再次指向http://localhost:8761 ,以在Eureka儀表板上查看其註冊狀態。通過使用儀表板,我們可以進行進一步的配置,例如將註冊客戶端的主頁與儀表板鏈接以進行管理。但是,配置選項不在本文討論範圍之內。

Spring

4. Feign Client

為了使用三個相關的微服務完成我們的項目,我們現在將使用Spring Netflix Feign Client實現一個使用REST Web應用程序。

Feign視為使用接口與端點進行通信的可發現發現的Spring RestTemplate 。該接口將在運行時自動實現,並且使用service-names代替service-urls

如果沒有Feign我們將不得不將EurekaClient一個實例自動EurekaClient到我們的控制器中,使用該實例我們可以收到一個以service-name為對象的服務信息作為Application對象。

我們將使用此Application獲取此服務的所有實例的列表,選擇一個合適的InstanceInfo ,然後使用此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添加以下四個依賴項:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-feign</artifactId>

 </dependency>

 <dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-netflix-eureka-client</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-thymeleaf</artifactId>

 </dependency>

Feign Client位於[spring-cloud-starter-feign](https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.cloud%22%20AND%20a%3A%22spring-cloud-starter-feign%22)軟件包中。要啟用它,我們必須使用@EnableFeignClients註釋@Configuration 。要使用它,我們只需使用@FeignClient(“service-name”)註釋一個接口並將其自動連接到控制器中即可。

創建此類Feign Clients一個好方法是使用@RequestMapping註釋方法創建接口,並將其放入單獨的模塊中。這樣,它們可以在服務器和客戶端之間共享。在服務器端,可以將它們實現為@Controller ,而在客戶端,可以將其擴展和註釋為@FeignClient

此外, spring-cloud-starter-eureka package需要包含在項目中,並通過使用@EnableEurekaClient註釋主應用程序類來@EnableEurekaClient

spring-boot-starter-webspring-boot-starter-thymeleaf依賴關係用於呈現視圖,其中包含從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模板:

<!DOCTYPE html>

 <html xmlns:th="http://www.thymeleaf.org">

 <head>

 <title>Greeting Page</title>

 </head>

 <body>

 <h2 th:text="${greeting}"/>

 </body>

 </html>

至少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 TransportException:無法在任何已知服務器上執行請求'

在運行Eureka服務器時,我們經常遇到以下異常:

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

基本上,這是由於application.propertiesapplication.yml的錯誤配置導致的。 Eureka為客戶端提供了兩個可配置的屬性。

  • registerWithEureka:如果我們將此屬性設置為true則在服務器啟動時,內置客戶端將嘗試向Eureka服務器註冊自身。
  • fetchRegistry:如果我們將此屬性配置為true,則內置客戶端將嘗試獲取Eureka註冊表。

現在,當我們啟動Eureka服務器時,我們不想註冊內置客戶端來使用server對其進行配置

如果在啟動服務器時將上述屬性標記為true (或默認情況下未將其配置為true ),則內置客戶端會嘗試向Eureka服務器註冊自身,並嘗試獲取尚不可用的註冊表。結果,我們得到TransportException

因此,我們永遠不要在Eureka服務器應用程序中將這些屬性配置為true 。下面給出了應放在application.yml中的正確設置:

eureka:

 client:

 registerWithEureka: false

 fetchRegistry: false

六,結論

如我們所見,我們現在能夠使用Spring Netflix Eureka Server實施服務註冊表並向其中註冊一些Eureka Clients

由於第3步中的Eureka Client監聽隨機選擇的端口,因此如果沒有註冊表中的信息,它就不會知道其位置。使用Feign Client和我們的註冊表,即使位置發生更改,我們也可以定位和使用REST服務。

最後,我們對在微服務架構中使用服務發現有了一個全面了解。

像往常一樣,您會[on GitHub ,](https://github.com/eugenp/tutorials/tree/master/spring-cloud/spring-cloud-eureka)找到源代碼[on GitHub ,](https://github.com/eugenp/tutorials/tree/master/spring-cloud/spring-cloud-eureka)該源代碼還包括一組與Docker相關的文件,可與docker-compose一起使用來從我們的項目中創建容器。