02 第一個Enreka的應用
本例將會編寫一個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的應用