spring-cloud微服務之路(三):服務註冊和發現之Eureka、Consul
在上一篇spring-cloud微服務之路(二):Spring Boot 我們介紹瞭如何快速的使用 Spring Boot 搭建一個微服務專案,這一篇我們演示如何分別使用 Spring Cloud Eureka 和 Spring Cloud Consul 完成服務註冊和發現的實現。
一:服務治理
服務治理可以說是微服務架構中最為核心和基礎的模組,它主要用來實現各個微服務例項的自動化註冊和發現。為什麼我們需要這麼一個功能,比如有兩個微服務 A 和 B ,其中 A 需要呼叫服務 B 來完成一個業務需求,為了實現服務 B 的高可用,無論採用服務端負載均衡還是客戶端負載均衡,都需要手動維護服務 B 的例項清單。但是隨著業務的發展,系統功能越來越複雜,響應的微服務也不斷增加,我們的靜態配置會變得越來越難以維護。並且面對不斷髮展的業務,我們的叢集規模、服務的位置、服務的命名都有可能發生變化,如果還是手動維護,極易造成很多不可預知的錯誤,消耗大量的人力。
這個時候服務治理的優勢就體現出來,在服務治理架構中,通常會有一個註冊中心,每個微服務向註冊中心註冊自己的服務,將主機號、版本號、通訊協議等資訊告知註冊中心,比如我們有兩個提供服務的 A 和 B, 待它們向註冊中心註冊完成以後,註冊中心會出現兩個服務,並且會通過心跳的方式檢測這兩個服務是否可用,如果不可用則剔除,達到排除故障的作用。同時由於在服務治理框架下運作,服務間的呼叫不再通過指定具體的例項地址實現,而是通過 服務名 發起請求呼叫實現,所以,服務呼叫方需要向服務註冊中心諮詢服務,應獲取所有服務的例項清單,以實現對具體服務例項的呼叫。比如 A 服務對應的地址是192.168.0.1:8080 ,應用名為 spring-cloud-providerA ,B 服務對應的地址是 192.168.0.1:8081,應用名為spring-cloud-providerB,服務 C spring-cloud-providerC首先也向註冊中心註冊,然後發現兩個提供服務的例項,通過服務應用名直接呼叫,不再關心這個服務在什麼IP 和 PORT 上。
二:使用 Eureka 搭建服務註冊中心
1、首先,建立一個基礎的 Spring Boot 專案,並在 pom.xml 中增加如下依賴:
<!--新增eureka服務註冊依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
在應用啟動類上面增加 @EnableEurekaServer
@EnableEurekaServer
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
2、在預設情況下,該服務註冊中心也會將自己作為客戶端來嘗試註冊自己,所以我們需要禁用它的客戶端註冊行為,只需要在 application.properties 檔案中新增如下配置:
#在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,
spring.application.name=spring-cloud-eureka
server.port=8080
#表示是否將自己註冊到Eureka Server,預設為true
eureka.client.register-with-eureka=false
#表示是否從Eureka Server檢索服務,預設為true,因為自己是維護服務的例項,不需要檢索服務,設定為false
eureka.client.fetch-registry=false
#設定與Eureka Server互動的地址,查詢服務和註冊服務都需要依賴這個地址。預設是http://localhost:8761/eureka ;多個地址可使用 , 分隔
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
3、在完成上面的配置後,啟動應用並訪問 http://localhost:8080 就可以看到 Eureka 的資訊面板,可以看到還沒有服務註冊到註冊中心。
二:註冊服務提供者
1、在完成服務註冊中心的搭建之後,接下來我們嘗試將一個 Spring Boot 應用加入到 Eureka 的服務治理體系中去。新建 Spring Boot 專案 eureka-provider ,修改 pom.xml ,增加 Spring Cloud Eureka 模組的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
2、接著建立 ProviderController,增加 index 介面,接收 name 引數,輸出 ‘hello’+ name + 'this is first message'
@RestController
public class ProviderController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String index(@RequestParam(value = "name") String name){
return "hello" + name + ", this is the first message";
}
}
3、然後在主啟動類上面增加 @EnableDiscoveryClient 註解開啟 Eureka 中的 DiscoveryClient 實現,注意:這一塊也可以使用 @EnableEurekaClient 註解,具體兩者之間的區別請參考 @EnableDiscoveryClient和@EnableEurekaClient區別
//spring-cloud-starter-eureka 和 spring-cloud-starter-consul-discovery
//均包含次註解
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
4、最後我們需要在 application.properties 配置檔案中,通過 spring.application.name 屬性來為服務命名,比如命名為spring-cloud-producer , 再通過 eureka.client.service-url.defaultZone 屬性來指定服務註冊中心的地址,也就是我們上面應用的地址:
spring.application.name=spring-cloud-producer
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
5、下面我們分別啟動剛開始建立的服務註冊中心應用和服務註冊提供者應用,瀏覽器輸入 http://localhost:8080/就可以看到服務已經註冊到服務中心。
三:服務發現與消費
通過上面的內容,我們已經搭建起服務註冊中心和服務註冊,服務發現的任務是由 Eureka 的客戶端實現,而消費的任務則是由 Ribbon 實現,Ribbon 是一個客戶端的負載均衡器。
1、首先,我們將上面建立的 eureka-provider 打成 jar 包 後使用命令分別啟動兩個不同的埠執行:
java -jar eureka-provider-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar eureka-provider-0.0.1-SNAPSHOT.jar --server.port=8082
2、在分別啟動成功後,如下圖所示,從 Eureka 資訊面板中我們看到名 SPRING-CLOUD-PRODUCER 的服務出現了兩個例項單元,埠分別是 8081 和 8082:
3、建立一個 Spring Boot 專案來實現服務消費者,取名為 ribbon-consumer ,並在 pom.xml 中引入如下的依賴內容,和以前的 eureka-provider 相比,我們新增了 Ribbon 模組的依賴 spring-cloud-starter-ribbon:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!--新增客戶端負載均衡元件ribbon ribbon呼叫方式-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
4、在應用主啟動類中增加 @EnableDiscoveryClient 註解讓該應用註冊為 Eureka 客戶端應用,同時在該類中建立 RestTemplate 的 Spring Bean 例項,並通過 @LoadBalanced 註解開啟客戶端的負載均衡。
//啟用服務註冊與發現
@EnableDiscoveryClient
//注意:這裡可以使用@SpringCloudApplication註解,
// 此註解包含@EnableDiscoveryClient/@SpringBootApplication/@EnableCircuitBreaker三個註解
@SpringBootApplication
public class RibbonConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
/**
* 新增ribbon客戶端負載均衡元件
* @return RestTemplate例項
*/
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
5、建立 ConsumerController 類提供 /ribbon-consumer 介面,在該介面中通過上面建立的 RestTemplate 來實現對SPRING-CLOUD-PRODUCER 服務提供的 /hello 介面進行呼叫。可以看到我們這裡訪問的是服務名 SPRING-CLOUD-PRODUCER ,而不是一個地址,這是一個非常重要的特性。
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/ribbon-consumer",method = RequestMethod.GET)
public String index(@RequestParam(name = "myname") String myname){
//restTemplate.getForObject("http://SPRING-CLOUD-PRODUCER/hello?name={1}",String.class,myname);第一種寫法
//下面是第二種寫法,注意這種寫法,不能這麼寫:getForObject("http://SPRING-CLOUD-PRODUCER/hello?name={xm}",String.class,new Hashmap<>().put("xm",myname));
Map<String,String> params = new HashMap<>();
params.put("xm",myname);
String result = restTemplate.getForObject("http://SPRING-CLOUD-PRODUCER/hello?name={xm}",String.class,params);
return result;
}
}
6、在配置檔案中將此應用註冊到Eureka註冊中心:
spring.application.name=spring-ribbon-consumer
server.port=2222
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
7、啟動應用,發現此消費應用已經成功註冊:
8、通過訪問 http://localhost:2222/ribbon-consumer?myname=測試 發起GET請求,成功返回 hello測試,this is first message 資訊,並且實現了請求輪詢,實現了負載均衡(大家可以將兩個提供者的輸出語句列印不同,這樣更加直觀)。
四:服務註冊和發現之Consul實現
待續。。。