爲了實現多個微服務之間的調用,咱們除了須要Feign這種調用組件外還得依賴服務發現組件。主要的緣由是每一個微服務所在的機器ip並不是老是固定的,而且每一個微服務均可能部署多個實例在不一樣的機器上,因此咱們不能把依賴的微服務ip地址寫在代碼或配置文件裏,咱們須要有個組件去動態的管理,這就是爲何微服務架構裏服務發現功能是必須的。html
那麼服務發現組件是怎麼實現服務發現的呢?咱們以你們比較熟悉的MySQL來作類比,經過MySQL簡單說明一下服務發現機制的實現。以下圖:java
簡單說明一下什麼是服務提供者與服務消費者:git
當微服務啓動的時候會向服務發現組件註冊自身信息,在上圖中就相似於向MySQL發送一條insert語句,將服務的元數據如服務名稱、ip地址及服務狀態等信息插入到MySQL中,如上圖的registry表數據所示,這個過程稱之爲服務註冊,因此服務發現組件內部會都維護相似於這樣的一張註冊表。github
微服務在註冊完成後,會讀取服務發現組件中保存的其餘微服務的元數據並緩存一份到本地,就相似於向MySQL發送一條select all語句。這樣在調用其餘服務的時候,就不須要每次都去服務發現組件上查詢,而是從本地緩存去查找調用地址,這樣能夠減輕服務發現組件的壓力。因此上圖中的調用箭頭並無指向服務發現組件,而是直接指向服務提供者。這樣的好處是哪怕是服務發現組件掛掉了,還能從本地緩存中獲取其餘微服務的調用地址。到這一步微服務之間就能夠互相發現了,即完成基本的服務發現spring
但微服務有可能會掛掉或下線,此時其餘服務不該該去發現一個不存在的服務。因此每一個服務啓動且向服務發現組件註冊完成以後,都會經過心跳機制告知存活狀態。上圖中用last_heartbeat字段表示,若某個服務在超過必定的時間都沒有發送心跳包的話,就會被服務發現組件檢測到,此時就會刪除註冊表裏該服務的註冊信息,並通知其餘服務更新本地緩存(如有新註冊的服務也會通知其餘服務更新本地緩存)。json
關於什麼是Nacos,官方文檔已經描述得很詳細了,Nacos官方文檔地址以下:瀏覽器
因此這裏只是簡單概述一下,Nacos與Eureka同樣,是服務發現組件,同時也是配置中心。Nacos解決了兩個問題,一是服務A如何找到服務B;二是管理微服務的配置,讓一個微服務的全部實例的配置都統一,而且能夠實現配置修改後自動刷新等。服務器
理論介紹也說得差很少了,本小節咱們來動手搭建一個Nacos Server。過程很簡單首先須要下載一個Nacos,下載地址以下:架構
而後咱們須要選擇一個合適的版本下載,即Nacos Server版本應儘可能與Client端的版本對應。至於Client的版本咱們能夠到工程的pom.xml文件中找到Spring Cloud Alibaba的依賴管理項點擊進去便可查看到:
以下能夠看到Nacos Client的版本爲1.0.0,因此與之對應選擇1.0.0版本的Nacos Server進行下載:
注:我這裏使用的Spring Cloud版本是Greenwich.SR1,Spring Cloud Alibaba的版本是0.9.0.RELEASE
因爲不是生產環境所用,其實也無需嚴格選擇對應的版本,只要能用就能夠了,因此我這裏選擇下載最新的1.1.0版本(通過測試可用):
下載並解壓後進入bin目錄,雙擊startup.cmd,或在命令行中輸入cmd startup.cmd便可運行Nacos Server:
啓動成功:
使用瀏覽器訪問localhost:8848
進入Nacos Server的管理頁面,此時須要輸入帳戶密碼,默認的帳戶密碼都是nacos:
登陸成功後,頁面以下:
該管理頁面支持中英文,可在右上角點擊切換:
官方文檔以下:
在上一小節中,咱們已經完成了Nacos Server的搭建,而這一小節將演示如何將微服務註冊到Nacos。我如今有一個用戶中心微服務,其pom.xml文件以下,包含了Spring Cloud Alibaba及Nacos Client依賴,Spring Boot版本爲2.1.6.RELEASE:
<dependencies> ... <!-- Nacos Client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <!--整合Spring Cloud--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!--整合Spring Cloud Alibaba--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>0.9.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在配置文件中配置一下nacos server的地址及端口:
spring: cloud: nacos: discovery: # 指定nacos server的地址 server-addr: 127.0.0.1:8848 application: # 服務名稱,必須的配置項,不然不會向nacos註冊 name: user-center ...
配置完成後啓動項目,而後到nacos server的管理頁面的服務列表上查看是否註冊成功,註冊成功的話會顯示在服務列表裏,以下:
點擊詳情能夠看到詳細信息:
通過以上這幾個步驟,就能夠很是簡單地整合Nacos Client,並將微服務註冊到Nacos Server上。經過一樣的步驟,我將另外一個內容中心微服務也註冊到Nacos Server上。咱們來寫一個簡單的測試用例,看看在內容中心上是否能發現用戶中心,代碼以下:
@Slf4j @SpringBootTest @RunWith(SpringRunner.class) public class DiscoveryClientTests { @Autowired private DiscoveryClient discoveryClient; /** * 測試服務發現,證實內容中心能找到用戶中心 */ @Test public void getServiceInstancesTest(){ // 獲取用戶中心微服務的全部實例信息 List<ServiceInstance> instances = discoveryClient.getInstances("user-center"); // 以json格式打印出來 log.info(JsonUtil.obj2JsonPretty(instances)); } }
控制檯輸出的json信息以下,證實經過服務發現組件能讓內容中心老是能找到用戶中心:
[ { "serviceId" : "user-center", "host" : "192.168.190.1", "port" : 8080, "secure" : false, "metadata" : { "nacos.instanceId" : "192.168.190.1#8080#DEFAULT#DEFAULT_GROUP@@user-center", "nacos.weight" : "1.0", "nacos.cluster" : "DEFAULT", "nacos.healthy" : "true", "preserved.register.source" : "SPRING_CLOUD" }, "uri" : "http://192.168.190.1:8080", "scheme" : null, "instanceId" : null } ]
下圖整理了Nacos服務發現的領域模型,咱們將圍繞該圖進行介紹:
一、上圖最外層的是Namespace,對應管理界面的命名空間,以下:
Namespace主要用做隔離,默認爲public,例如咱們有三個環境:開發、測試及生產環境,那麼就能夠建立三個Namespace,不一樣的Namespace之間是互相隔離的。
舉個例子,咱們能夠來建立一個開發環境專用的命名空間:
建立完成後能夠看到每一個命名空間都會有本身的惟一命名空間id:
那麼微服務要如何註冊到指定的命名空間呢?很簡單,在配置文件中經過namespace配置項指定便可:
spring: cloud: nacos: discovery: # 指定nacos server的地址 server-addr: 127.0.0.1:8848 # 配置命名空間 namespace: 4a557407-c2c8-4524-97a0-17aa3c836407 ...
配置完成後重啓項目,此時該服務再也不是註冊到以前的public命名空間,而是註冊到咱們剛剛建立的dev命名空間,此時在dev下的微服務是看不到public下的微服務的,即實現了環境隔離了:
二、在Namespace之下是Group服務分組,默認的Group是DEFAULT_GROUP。咱們能夠在服務列表中看到:
Group能夠將不一樣的微服務劃分到同一個分組裏,Group可讓咱們方便去分組管理微服務。但須要注意的是,在目前的Spring Cloud Alibaba版本,並無用上這個Group,應該會在將來的版本上支持。
三、而Group下面是Service,Service既是微服務,例如用戶微服務、訂單微服務等。每一個Service能夠包含多個Cluster(集羣),Cluster是對指定微服務的一個虛擬劃分,默認爲DEFAULT。比方說公司內有北京機房、上海機房的服務器,那麼爲了異地容災,用戶中心微服務就可能會被同時部署在北京機房和上海機房。這時候咱們就能夠爲北京機房的用戶中心微服務實例劃分到一個集羣裏而且起一個集羣名稱,而上海機房的用戶中心微服務實例同理。將微服務實例劃分到一個集羣后,咱們還能夠實現相似於讓上海機房裏的微服務儘可能調用同機房內的其餘微服務,這樣在容災的同時還能夠提高性能。
關於集羣咱們能夠直接在配置文件中配置,而不用像命名空間那樣須要提早建立,以下:
spring: cloud: nacos: discovery: # 指定nacos server的地址 server-addr: 127.0.0.1:8848 # 配置集羣名稱,名稱能夠任意 cluster-name: BJ ...
配置完成後重啓項目,此時能夠看到該微服務實例處於BJ集羣下,而不是處於以前默認的DEFAULT集羣下:
四、Cluster裏是Instance,即上面所提到的微服務實例
關於這些概念的官方文檔地址以下:
什麼是Nacos元數據,官方文檔描述以下:
Nacos數據(如配置和服務)描述信息,如服務版本、權重、容災策略、負載均衡策略、鑑權配置、各類自定義標籤 (label),從做用範圍來看,分爲服務級別的元信息、集羣的元信息及實例的元信息。
- 服務級別的元信息在服務詳情中展現
- 集羣的元信息在集羣配置中展現
- 實例的元信息在集羣實例表內展現
元數據做用:
配置元數據的兩種方式:
在Nacos Server的管理頁面設置;以服務的元數據示例,在服務詳情頁面點擊編輯服務後,在元數據這欄輸入json格式的元數據便可:
spring: cloud: nacos: discovery: # 指定nacos server的地址 server-addr: 127.0.0.1:8848 # 這種方式配置的是實例級別的元數據 metadata: # k-v形式,k和v均可以自定義 instance: c test: a version: v1
配置完成後重啓項目,能夠看到配置文件中所配置的實例級別元數據: