1. 程式人生 > >02 第一個Enreka的應用

02 第一個Enreka的應用

eureka b- pom.xml文件 str ins .net frame dep .data

  本例將會編寫一個Hello world 小程序來演示Eureka的作用,程序中將會包含服務器、服務提供者以及服務的調用者

1. 構建服務器

  先創建一個名稱為first-ek-server的maven項目作為服務器,項目的目錄結構如下

  技術分享圖片

  在pom.xml文件中添加Spring Cloud的依賴

pom.xml代碼清單  

技術分享圖片View Code

  由於引入的spring-cloud-starter-eureka-server會自動引入spring-boot-starter-web依賴,因此只要我們的項目引入該依賴,項目就有了web容器的功能了。接下來我們編寫一個啟動類來啟動我們的Eureka服務器

FirstServer.java

技術分享圖片View Code

  啟動類與Spring Boot項目的啟動類基本一致,這裏加入的@EnableEurekaServer是聲明這是一個Eureka的服務器。此時直接運行FirstServer.java的啟動類就可以啟動Eureka服務器,在這裏我們在application.yml文件中將啟動端口改為8761,啟動成功後的界面如圖所示

技術分享圖片

  打開瀏覽器,輸入http://localhost:8761,就可以看到Eureka服務器的控制臺。

技術分享圖片

  在Eureka控制臺的下方,可以看到服務的實例列表,但是我們目前沒有註冊服務,所以此時服務列表為空,此時看到的UNKNOWN是服務器自己註冊的服務。

  值得註意的是,我們在啟動Eureka服務器的時候,在IDEA的控制臺上會看到兩個異常信息

技術分享圖片

技術分享圖片

  這是由於服務器在啟動時,服務器會把自己當做一個客戶端,去註冊Eureka服務器,並且會去Eureka服務器抓取註冊信息,他自己本身只是一個服務器,並不是服務器的提供者(客戶端),因此我們需要在application.xml文件修改這兩個配置阻止服務器註冊和抓取信息,修改內容如下

  技術分享圖片

  eureka.client.register-with-eureka屬性的作用是聲明是否將自己的信息註冊到Eureka服務器,默認為true,eureka.client.fetch-registy屬性則表示是否發哦服務器中抓取信息,默認也是true.我們將其設置為false,再啟動服務器就不會出現異常信息。

  此時,我們的Eureka服務器已經創建好了,接下來我們就來編寫Eureka客戶端的服務提供者。

2.編寫服務提供者

  創建一個maven項目作為服務的提供者,項目的目錄結構如下

  技術分享圖片

  在pom.xml中引入相關的依賴

  pom.xml清單

技術分享圖片
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.triheart</groupId>
 8     <artifactId>first-service-provider</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <dependencyManagement>
12         <dependencies>
13             <dependency>
14                 <groupId>org.springframework.cloud</groupId>
15                 <artifactId>spring-cloud-dependencies</artifactId>
16                 <version>Dalston.SR1</version>
17                 <type>pom</type>
18                 <scope>import</scope>
19             </dependency>
20         </dependencies>
21     </dependencyManagement>
22 
23     <dependencies>
24         <dependency>
25             <groupId>org.springframework.cloud</groupId>
26             <artifactId>spring-cloud-starter-config</artifactId>
27         </dependency>
28         <dependency>
29             <groupId>org.springframework.cloud</groupId>
30             <artifactId>spring-cloud-starter-eureka</artifactId>
31         </dependency>
32     </dependencies>
33 
34 </project>
View Code

  application.xml清單

技術分享圖片
spring:
  application:
    name: first-service-provider
eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
View Code

  在這裏,將應用名稱配置為first-service-provider,該服務會被註冊到端口為8761的Eureka服務器,也就是上面構建的服務器。此外,還使用eureka.instance.hostname屬性來配置該主機的名稱。然後我們在編寫一個Controller類,並提供最簡單的REST服務,先創建一個Person的實體類,用於Controller對象的數據發送和接收。

  Person.java的代碼清單

技術分享圖片
 1 package com.triheart.firstserviceprovider.entity;
 2 
 3 public class Person {
 4 
 5     private Integer id;
 6     
 7     private String name;
 8     
 9     private Integer age;
10 
11     public Person() {
12         super();
13     }
14 
15     public Person(Integer id, String name, Integer age) {
16         super();
17         this.id = id;
18         this.name = name;
19         this.age = age;
20     }
21 
22     public Integer getId() {
23         return id;
24     }
25 
26     public void setId(Integer id) {
27         this.id = id;
28     }
29 
30     public String getName() {
31         return name;
32     }
33 
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     public Integer getAge() {
39         return age;
40     }
41 
42     public void setAge(Integer age) {
43         this.age = age;
44     }
45     
46 }
View Code

  FirstController.java代碼清單

技術分享圖片
package com.triheart.firstserviceprovider.controller;

import com.triheart.firstserviceprovider.entity.Person;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 阿遠
 * Date: 2018/8/23
 * Time: 16:06
 */
@RestController
public class FirstController {

    @RequestMapping(value = "/person/{personId}",method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
    public Person findPerson(@PathVariable("personId") Integer personId) {
        Person person = new Person(personId, "eureka",30);
        return person;
    }
}
View Code

  編寫啟動類FirstServiceProvider.java

  FirstServiceProvider.java代碼清單

技術分享圖片
 1 package com.triheart.firstserviceprovider;
 2 
 3 import org.springframework.boot.autoconfigure.SpringBootApplication;
 4 import org.springframework.boot.builder.SpringApplicationBuilder;
 5 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 6 
 7 /**
 8  * @author 阿遠
 9  * Date: 2018/8/23
10  * Time: 15:47
11  */
12 @SpringBootApplication
13 @EnableEurekaClient
14 public class FirstServiceProvider {
15     public static void main(String[] args) {
16         new SpringApplicationBuilder(FirstServiceProvider.class).run(args);
17     }
18 }
View Code

  在上面的啟動類中,使用到了@EnableEurekaClient的註解,聲明這是一個Eureka的客戶端。配置完成後,我們先啟動服務器項目first-ek-server的啟動類FirstServer,再運行服務提供者項目first-server-provider的啟動類FirstServiceProvider,然後再在瀏覽器中訪問http://localhost:8761/,就可以看到如下所示的服務列表。

技術分享圖片

  在Eureka的控制臺的服務列表中我們可以看到first-server-provider這個服務已經被註冊進來,而且我們在IDEA的控制臺裏也可以看到服務被註冊的信息。

技術分享圖片

  此時,Eureka服務器和Eureka客戶端的服務提供者都已經搞定了,接下來我們就來編寫Eureka客戶端的服務調用者。

3.編寫服務調用者

  服務被註冊、發布到Eureka服務器後,需要有程序去發現它,並且進行調用。這裏所說調用的調用者,是指同樣註冊到Eureka的客戶端,它來調用其他客戶端發布的服務。簡單地說,就是Eureka的內部調用。同一個服務可能會部署多個實例,調用過程可能會涉及到負載均衡、服務器查找等問題,Netflix的項目已經幫我們解決,並且在Spring Cloud中已經封裝了一次,我們僅需編寫少量的代碼便能實現服務的調用。

  新建一個maven項目,用於做Eureka客戶端的服務調用者,目錄結構如下

技術分享圖片

  在pom.xml文件中引入相關依賴

  pom.xml代碼清單

技術分享圖片
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.triheart</groupId>
 8     <artifactId>first-ek-service-invoker</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <dependencyManagement>
12         <dependencies>
13             <dependency>
14                 <groupId>org.springframework.cloud</groupId>
15                 <artifactId>spring-cloud-dependencies</artifactId>
16                 <version>Dalston.SR1</version>
17                 <type>pom</type>
18                 <scope>import</scope>
19             </dependency>
20         </dependencies>
21     </dependencyManagement>
22 
23     <dependencies>
24         <dependency>
25             <groupId>org.springframework.cloud</groupId>
26             <artifactId>spring-cloud-starter-config</artifactId>
27         </dependency>
28         <dependency>
29             <groupId>org.springframework.cloud</groupId>
30             <artifactId>spring-cloud-starter-eureka</artifactId>
31         </dependency>
32         <dependency>
33             <groupId>org.springframework.cloud</groupId>
34             <artifactId>spring-cloud-starter-ribbon</artifactId>
35         </dependency>
36     </dependencies>
37 
38 </project>
View Code

  建立配置文件application.yml

  application.yml代碼清單

技術分享圖片
 1 server:
 2   port: 9000
 3 spring:
 4   application:
 5     name: first-service-invoker
 6 eureka:
 7   instance:
 8     hostname: localhost
 9   client:
10     service-url:
11       defaultZone: http://localhost:8761/eureka/
View Code

  在這個配置文件中,我們配置了應用名稱為first-service-invoker,這個調用者的訪問端口為9000,需要註意的是,這個調用本身也可以對外提供服務。與服務的提供者一樣,使用eureka的配置,將調用者也註冊到first-ek-server上面。接下來我們編寫一個控制器,讓調用者對外提供一個測試的服務。

  創建InvokerController.java控制器

  InvokerController.java代碼清單

技術分享圖片
 1 package com.triheart.firstekserviceinvoker.controller;
 2 
 3 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 4 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.http.MediaType;
 8 import org.springframework.web.bind.annotation.RequestMapping;
 9 import org.springframework.web.bind.annotation.RequestMethod;
10 import org.springframework.web.bind.annotation.RestController;
11 import org.springframework.web.client.RestTemplate;
12 
13 /**
14  * @author 阿遠
15  * Date: 2018/8/23
16  * Time: 17:56
17  */
18 @RestController
19 @Configuration
20 public class InvokerController {
21 
22     @Bean
23     @LoadBalanced
24     public RestTemplate getRestTemplate() {
25         return new RestTemplate();
26     }
27 
28     @RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE
29     )
30     public String router() {
31         RestTemplate restTemplate = getRestTemplate();
32         // 根據應用名稱調用服務
33         String json = restTemplate.getForObject("hTTP://first-service-provider/person/1", String.class);
34         return json;
35     }
36 }
View Code

  在控制器中,配置RestTemplate的Bean,RestTemplate本來是spring-web模塊下面的類,主要用來調用REST服務。其本身並不具備調用分布式服務的能力,但是RestTemplate的Bean被@LoadBalabced註解修飾後,這個RestTemplate實例就具有了訪問分布式服務的能力了。我們在控制器中新建了一個router的測試方法,用來對外發布REST服務,該方法只起到路由的作用,實際上是使用RestTemplate來調用first-ek-service-provider(服務提供者)的服務。調用服務時,僅僅通過服務名稱調用。

  創建FirstInvoker.java啟動類

  FirstInvoker.java啟動類

技術分享圖片
 1 package com.triheart.firstekserviceinvoker;
 2 
 3 import org.springframework.boot.autoconfigure.SpringBootApplication;
 4 import org.springframework.boot.builder.SpringApplicationBuilder;
 5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 6 
 7 /**
 8  * @author 阿遠
 9  * Date: 2018/8/23
10  * Time: 17:51
11  */
12 @SpringBootApplication
13 @EnableDiscoveryClient
14 public class FirstInvoker {
15 
16     public static void main(String[] args) {
17         new SpringApplicationBuilder(FirstInvoker.class).run(args);
18     }
19 }
View Code

  在啟動類中,使用了@EnableDiscoveryClient註解來修飾啟動類,該註解是的服務的調用者有能力去Eureka中發現服務。需要註意的是,@EnableEurekaClient註解本身已經包含了@EnableDiscoveryClient的功能,也就是說,一個Eureka客戶端本身就具有發現服務的能力。

  接下來,我們按如下的順序啟動項目

  a.啟動服務器(first-ek-server)

  b.啟動服務提供者(first-service-provider)

  c.啟動服務調用者(first-ek-service-invoker)

  啟動完成後訪問http://localhost:8761/可以看到註冊的服務調用者的信息

技術分享圖片

  然後我們在瀏覽器中訪問http://localhost:9000/router,可以在瀏覽器中看到

技術分享圖片

  根據這個輸出我們可以知道,Eureka客戶端(服務調用者)實際上是調用了服務提供者的/person/1的服務,第一個Eureka應用到此結束。

4.程序結構總結

  本案例創建了三個項目,項目結構如圖所示

技術分享圖片

  Eureka服務器為本例中的first-ek-server,Eureka客戶端(服務發布者)為本例的first-service-provider,Eureka客戶端(服務調用者)為本例的first-ek-service-invoker,而用戶通過瀏覽器訪問調用者的9000端口的router服務來查找服務提供者的服務並調用,此處的服務調用有點像路由器的角色。

  

02 第一個Enreka的應用