源碼地址:https://gitee.com/fighter3/eshop-project.git
持續更新中……
在上一節我們已經完成了Nacos Server的本地部署,這一節我們學習如何將Nacos作為注冊中心,管理微服務。
1、注冊中心簡介
1.1、什么是注冊中心
在微服務的體系里,注冊中心是最重要的組件之一,我們來簡單了解一下什么是注冊中心。
注冊中心和DNS類似,大家想一想,我們平時訪問百度,是訪問 www.baidu.com ,還是直接訪問ip地址呢?
注冊中心就承擔了這樣一個“名單”的角色,它記錄了服務和服務地址的映射關系。在分布式架構中,服務會注冊到這里,當服務需要調用其它服務時,就到這里找到服務的地址,進行調用。
注冊中心的作用就是服務的注冊和服務的發現。
1.2、常見的注冊中心
- Netflix Eureka
- Alibaba Nacos
- HashiCorp Consul
- Apache ZooKeeper
- CoreOS Etcd
- CNCF CoreDNS
特性 | Eureka | Nacos | Consul | Zookeeper |
---|---|---|---|---|
CAP | AP | CP + AP | CP | CP |
健康檢查 | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
雪崩保護 | 有 | 有 | 無 | 無 |
自動注銷實例 | 支持 | 支持 | 不支持 | 支持 |
訪問協議 | HTTP | HTTP/DNS | HTTP/DNS | TCP |
監聽支持 | 支持 | 支持 | 支持 | 支持 |
多數據中心 | 支持 | 支持 | 支持 | 不支持 |
跨注冊中心同步 | 不支持 | 支持 | 支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
1.3、CAP原則與BASE理論
1.3.1、CAP原則
CAP 原則又稱 CAP 定理,指的是在一個分布式系統中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性),三者不可得兼。
CAP 由 Eric Brewer 在 2000 年 PODC 會議上提出。該猜想在提出兩年后被證明成立,成為我們熟知的 CAP 定理。CAP 三者不可兼得。
特性 | 定理 |
---|---|
Consistency | 也叫做數據原子性,系統在執行某項操作后仍然處於一致的狀態。在分布式系統中,更新操作執行成功后所有的用戶都應該讀到最新的值,這樣的系統被認為是具有強一致性的。等同於所有節點訪問同一份最新的數據副本。 |
Availability | 每一個操作總是能夠在一定的時間內返回結果,這里需要注意的是"一定時間內"和"返回結果"。一定時間內指的是,在可以容忍的范圍內返回結果,結果可以是成功或者是失敗。 |
Partition tolerance | 在網絡分區的情況下,被分隔的節點仍能正常對外提供服務(分布式集群,數據被分布存儲在不同的服務器上,無論什么情況,服務器都能正常被訪問)。 |
取舍原則
CAP 三個特性只能滿足其中兩個,那么取舍的策略就共有三種:
- CA without P:如果不要求P(不允許分區),則C(強一致性)和A(可用性)是可以保證的。但放棄 P 的同時也就意味着放棄了系統的擴展性,也就是分布式節點受限,沒辦法部署子節點,這是違背分布式系統設計的初衷的。
- CP without A:如果不要求A(可用),相當於每個請求都需要在服務器之間保持強一致,而P(分區)會導致同步時間無限延長(也就是等待數據同步完才能正常訪問服務),一旦發生網絡故障或者消息丟失等情況,就要犧牲用戶的體驗,等待所有數據全部一致了之后再讓用戶訪問系統。設計成 CP 的系統其實不少,最典型的就是分布式數據庫,如 Redis、HBase 等。對於這些分布式數據庫來說,數據的一致性是最基本的要求,因為如果連這個標准都達不到,那么直接采用關系型數據庫就好,沒必要再浪費資源來部署分布式數據庫。
- AP without C:要高可用並允許分區,則需放棄一致性。一旦分區發生,節點之間可能會失去聯系,為了高可用,每個節點只能用本地數據提供服務,而這樣會導致全局數據的不一致性。典型的應用就如某米的搶購手機場景,可能前幾秒你瀏覽商品的時候頁面提示是有庫存的,當你選擇完商品准備下單的時候,系統提示你下單失敗,商品已售完。這其實就是先在 A(可用性)方面保證系統可以正常的服務,然后在數據的一致性方面做了些犧牲,雖然多少會影響一些用戶體驗,但也不至於造成用戶購物流程的嚴重阻塞。
總結:
現如今,對於多數大型互聯網應用的場景,主機眾多、部署分散,而且現在的集群規模越來越大,節點只會越來越多,所以節點故障、網絡故障是常態,因此分區容錯性也就成為了一個分布式系統必然要面對的問題。那么就只能在 C 和 A 之間進行取舍。但對於傳統的項目就可能有所不同,拿銀行的轉賬系統來說,涉及到金錢的對於數據一致性不能做出一絲的讓步,C 必須保證,出現網絡故障的話,寧可停止服務,可以在 A 和 P 之間做取舍。
總而言之,沒有最好的策略,好的系統應該是根據業務場景來進行架構設計的,只有適合的才是最好的。
1.3.2、BASE理論
CAP 理論已經提出好多年了,難道真的沒有辦法解決這個問題嗎?也許可以做些改變。比如 C 不必使用那么強的一致性,可以先將數據存起來,稍后再更新,實現所謂的 “最終一致性”。
這個思路又是一個龐大的問題,同時也引出了第二個理論 BASE 理論。
BASE:全稱 Basically Available(基本可用),Soft state(軟狀態),和 Eventually consistent(最終一致性)三個短語的縮寫,來自 ebay 的架構師提出。
BASE 理論是對 CAP 中一致性和可用性權衡的結果,其來源於對大型互聯網分布式實踐的總結,是基於 CAP 定理逐步演化而來的。其核心思想是:
既然無法做到強一致性(Strong consistency),但每個應用都可以根據自身的業務特點,采用適當的方式來使系統達到最終一致性(Eventual consistency)。
Basically Available(基本可用)
基本可用是指分布式系統在出現故障的時候,允許損失部分可用性(例如響應時間、功能上的可用性)。需要注意的是,基本可用絕不等價於系統不可用。
- 響應時間上的損失:正常情況下搜索引擎需要在 0.5 秒之內返回給用戶相應的查詢結果,但由於出現故障(比如系統部分機房發生斷電或斷網故障),查詢結果的響應時間增加到了 1~2 秒。
- 功能上的損失:購物網站在購物高峰(如雙十一)時,為了保護系統的穩定性,部分消費者可能會被引導到一個降級頁面。
Soft state(軟狀態)
什么是軟狀態呢?相對於原子性而言,要求多個節點的數據副本都是一致的,這是一種 “硬狀態”。
軟狀態是指允許系統存在中間狀態,而該中間狀態不會影響系統整體可用性。分布式存儲中一般一份數據會有多個副本,允許不同副本數據同步的延時就是軟狀態的體現。
Eventually consistent(最終一致性)
系統不可能一直是軟狀態,必須有個時間期限。在期限過后,應當保證所有副本保持數據一致性。從而達到數據的最終一致性。這個時間期限取決於網絡延時,系統負載,數據復制方案設計等等因素。
實際上,不只是分布式系統使用最終一致性,關系型數據庫在某個功能上,也是使用最終一致性的,比如備份,數據庫的復制都是需要時間的,這個復制過程中,業務讀取到的值就是舊值。當然,最終還是達成了數據一致性。這也算是一個最終一致性的經典案例。
總結
總的來說,BASE 理論面向的是大型高可用可擴展的分布式系統,和傳統事務的 ACID 是相反的,它完全不同於 ACID 的強一致性模型,而是通過犧牲強一致性來獲得可用性,並允許數據在一段時間是不一致的。
2、引入Nacos作為注冊中心
啟動Nacos Server,我們發現服務列表里空空如也,接下里我們會在項目里集成Nacos Client,把我們前面開發的服務注冊到Nacos Server。
2.1、引入Nacos Client
Nacos與SpringCloud\Dubbo生態都能很好的融合,我們基於spring-cloud-alibaba引入nacos基礎jar。
首先將父項目引入spring-cloud\spring-cloud-alibaba依賴,首先看一下官方的版本說明:版本說明
SpringBoot我們引入的是2.2.2.RELEASE
版本,所以SpringCloud版本選擇Hoxton.RELEASE
,SpringCloud Alibaba版本選擇2.2.0.RELEASE
。
- 父項目管理依賴版本
在父項目pom.xml中添加:
<properties>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 子項目引入Nacos
還是以user子模塊為例,在user子模塊的pom.xml中添加:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
這里存在一個問題,spring-cloud-starter-alibaba-nacos-discovery需要指定版本,否則無法導入,沒有查找為什么版本和SpringCloud Alibaba版本不一致。
2.2、服務注冊
- 在模塊啟動類中添加注解
@EnableDiscoveryClient
開啟服務注冊發現功能
@SpringBootApplication
@MapperScan("cn.fighter3.mapper")
@EnableDiscoveryClient
public class EshopUserApplication {
public static void main(String[] args) {
SpringApplication.run(EshopUserApplication.class, args);
}
}
- 在配置文件application.yml中添加服務名稱和Nacos Server地址
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
更多配置可以查看:Nacos discovery
- 啟動項目,通過Nacos控制台查看,發現用戶服務已經注冊到了Nacos Server。
我們可以參考第五章,和上面的內容,完善其它幾個業務子模塊,將其它幾個業務模塊服務也注冊到Nacos注冊中心。這里略去這一部分的內容,給大家看最后的效果:
好了,服務注冊已經完成,在下一章我們會接着學習服務如何遠程調用,請持續關注……
"簡單的事情重復做,重復的事情認真做,認真的事情有創造性地做!"——
我是三分惡,可以叫我老三/三分/三哥/三子,一個能文能武的全棧開發,咱們下期見!
參考:
【1】:小專欄《SpringCloudAlibaba微服務實戰 》
【3】:Spring Cloud 系列之 Alibaba Nacos 注冊中心(一)
【4】:Nacos discovery