Spring Cloud構建微服務架構:服務註冊與發現(Eureka)
1. Spring Cloud簡介
Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中涉及的配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式。
Spring Cloud 全家桶:
- | Spring Cloud |
---|---|
服務註冊中心 | Spring Cloud Netflix Eureka |
服務呼叫方式 | REST API |
服務閘道器 | Spring Cloud Netflix Zuul |
斷路器 | Spring Cloud Netflix Hystrix |
分散式配置 | Spring Cloud Config |
服務跟蹤 | Spring Cloud Sleuth |
訊息匯流排 | Spring Cloud Bus |
資料流 | Spring Cloud Stream |
批量任務 | Spring Cloud Task |
2. 微服務架構
微服務架構就是將一個完整的應用從資料儲存開始垂直拆分成多個不同的服務,每個服務都能獨立部署、獨立維護、獨立擴充套件,服務與服務間通過諸如RESTful API的方式互相呼叫。各個微服務之間是鬆耦合的,每個微服務僅關注於完成一件任務,每個任務代表著一個小的業務能力。
3. 服務治理
服務治理是實現微服務的關鍵。那麼有沒有好的服務治理方案呢?我想大家都聽過或者使用過dubbo,dubbo就是一個帶有服務治理功能的RPC框架。dubbo提供了一套較為完整的服務治理方案,所以企業如果要實現服務化的話,dubbo是很好的一個選擇。
服務發現與註冊作為服務治理最最重要的問題,dubbo中引入了一個註冊中心的概念,而zookeeper作為dubbo推薦的註冊中心,承擔了及其重要的作用。
那麼我們如何使用Spring Cloud來實現服務治理呢?答案就是Spring Cloud Eureka,也就是本篇部落格要介紹的重點。Spring Cloud Eureka是Spring Cloud Netflix專案下的服務治理模組。而Spring Cloud Netflix專案是Spring Cloud的子專案之一,主要內容是對Netflix公司一系列開源產品的包裝,它為Spring Boot應用提供了自配置的Netflix OSS整合。通過一些簡單的註解,開發者就可以快速的在應用中配置一下常用模組並構建龐大的分散式系統。它主要提供的模組包括:服務發現(Eureka),斷路器(Hystrix),智慧路由(Zuul),客戶端負載均衡(Ribbon)等。
以下是筆者翻閱資料後對zookeeper和eureka進行的比較總結:
-
Eureka 保證AP Eureka中各個節點都是平等的,幾個節點掛掉不會影響正常節點的工作,剩餘節點依然可以提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊時如果發現連線失敗,則會自動切換至其它節點,從而保證註冊服務可用(保證可用性),只不過查到的資訊可能不是最新的(不保證強一致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鐘內超過85%的節點都沒有正常的心跳,那麼Eureka就認為客戶端與註冊中心出現了網路故障,此時會出現以下幾種情況:
- Eureka不再從註冊列表中移除因為長時間沒收到心跳而應該過期的服務。
- Eureka仍然能夠接受新服務的註冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用)。
- 當網路穩定時,當前Eureka新的註冊資訊會被同步到其它節點中。
Eureka還有客戶端快取功能
-
Zookeeper 保證CP 當master節點因為網路故障與其他節點失去聯絡時,剩餘節點會重新進行leader選舉。在選舉期間整個zk叢集都是不可用的,這就導致在選舉期間註冊服務癱瘓。
4. 動手搭服務發現和註冊
第一步:建立服務註冊中心
建立Spring boot專案,命名為eureka-server,並在pom.xml中引入需要的依賴內容:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 引入Eureka服務包-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
通過@EnableEurekaServer註解啟動一個服務註冊中心提供給其他應用進行對話。在Spring Boot啟動類加上這個註解即可,如下:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,只需要在application.properties配置檔案中增加如下資訊:
spring.application.name=eureka-server
server.port=8761
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka
#表示是否將自己註冊到Eureka Server上,預設為true
eureka.client.registerWithEureka=false
#表示是否從Eureka Server上獲取註冊資訊,預設為true
eureka.client.fetchRegistry=false
啟動工程,訪問 http://localhost:8761/ ,可以看到下面的頁面,其中還沒有發現任何服務。 第二步:建立服務提供方
下面我們建立提供服務的客戶端,並向服務註冊中心註冊自己。本文我們主要介紹服務的註冊與發現,所以我們不妨在服務提供方中嘗試著提供一個介面來獲取當前所有的服務資訊。
首先,建立一個基本的Spring Boot應用。命名為eureka-order,在pom.xml中,加入如下配置:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在應用啟動類中通過加上@EnableEurekaClient(該註解上有@EnableDiscoveryClient)註解,該註解能啟用Eureka中的DiscoveryClient實現,這樣才能實現Controller中對服務資訊的輸出。
@SpringBootApplication
@EnableEurekaClient
public class EurekaOrderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaOrderApplication.class, args);
}
}
我們在完成以上工作後,再繼續對eureka-order的application.properties做一些配置工作,具體如下:
spring.application.name=eureka-order
server.port=8100
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka
通過spring.application.name屬性,我們可以指定微服務的名稱後續在呼叫的時候只需要使用該名稱就可以進行服務的訪問。eureka.client.serviceUrl.defaultZone屬性對應服務註冊中心的配置內容,指定服務註冊中心的位置。為了在本機上測試區分服務提供方和服務註冊中心,使用server.port屬性設定不同的埠。