服務發現
爲了實現多個微服務之間的調用,我們除了需要Feign這種調用組件外還得依賴服務發現組件。主要的原因是每個微服務所在的機器ip並非總是固定的,並且每個微服務都可能部署多個實例在不同的機器上,所以我們不能把依賴的微服務ip地址寫在代碼或配置文件裏,我們需要有個組件去動態的管理,這就是爲什麼微服務架構裏服務發現功能是必須的。
那麼服務發現組件是怎麼實現服務發現的呢?我們以大家比較熟悉的MySQL來做類比,通過MySQL簡單說明一下服務發現機制的實現。如下圖:
簡單說明一下什麼是服務提供者與服務消費者:
· 服務提供者:服務的被調用方(即:爲其他微服務提供接口的微服務)
· 服務消費者:服務的調用方(即:調用其他微服務接口的微服務)
· 例如:訂單服務需要調用用戶服務的接口,那麼訂單服務就是服務消費者,而用戶服務則是服務提供者
· 服務提供者與服務消費者實際描述的是微服務之間的調用關係,一般都是成對出現的
當微服務啓動的時候會向服務發現組件註冊自身信息,在上圖中就類似於向MySQL發送一條insert語句,將服務的元數據如服務名稱、ip地址及服務狀態等信息插入到MySQL中,如上圖的registry表數據所示,這個過程稱之爲服務註冊,所以服務發現組件內部會都維護類似於這樣的一張註冊表。
微服務在註冊完成後,會讀取服務發現組件中保存的其他微服務的元數據並緩存一份到本地,就類似於向MySQL發送一條select all語句。這樣在調用其他服務的時候,就不需要每次都去服務發現組件上查詢,而是從本地緩存去查找調用地址,這樣可以減輕服務發現組件的壓力。所以上圖中的調用箭頭並沒有指向服務發現組件,而是直接指向服務提供者。這樣的好處是哪怕是服務發現組件掛掉了,還能從本地緩存中獲取其他微服務的調用地址。到這一步微服務之間就可以互相發現了,即完成基本的服務發現
但微服務有可能會掛掉或下線,此時其他服務不應該去發現一個不存在的服務。所以每個服務啓動且向服務發現組件註冊完成之後,都會通過心跳機制告知存活狀態。上圖中用last_heartbeat字段表示,若某個服務在超過一定的時間都沒有發送心跳包的話,就會被服務發現組件檢測到,此時就會刪除註冊表裏該服務的註冊信息,並通知其他服務更新本地緩存(若有新註冊的服務也會通知其他服務更新本地緩存)。
搭建Nacos Server
關於什麼是Nacos,官方文檔已經描述得很詳細了,Nacos官方文檔地址如下:
https://nacos.io/zh-cn/docs/what-is-nacos.html
所以這裏只是簡單概述一下,Nacos與Eureka一樣,是服務發現組件,同時也是配置中心。Nacos解決了兩個問題,一是服務A如何找到服務B;二是管理微服務的配置,讓一個微服務的所有實例的配置都統一,並且可以實現配置修改後自動刷新等。
理論介紹也說得差不多了,本小節我們來動手搭建一個Nacos Server。過程很簡單首先需要下載一個Nacos,下載地址如下:
https://github.com/alibaba/nacos/releases
然後我們需要選擇一個合適的版本下載,即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:
登錄成功後,頁面如下:
該管理頁面支持中英文,可在右上角點擊切換:
官方文檔如下:
https://nacos.io/zh-cn/docs/quick-start.html
將微服務註冊到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