Nacos 解读:服务发现客户端
Nacos可以分為服務發現(Naming)和配置管理(Config)兩塊,而從使用上來說,又可分為Nacos服務端和客戶端,第一篇先來聊下服務發現(Naming)的客戶端。
Example
我們從官方示例入手。
Properties properties = new Properties();
properties.setProperty("serverAddr", System.getProperty("serverAddr"));
properties.setProperty("namespace", System.getProperty("namespace"));
NamingService naming = NamingFactory.createNamingService(properties);
naming.registerInstance("nacos.test.3", "11.11.11.11", 8888, "TEST1");
naming.registerInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("nacos.test.3"));
naming.deregisterInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("nacos.test.3"));
naming.subscribe("nacos.test.3", new EventListener() {
@Override
public void onEvent(Event event) {
System.out.println(((NamingEvent)event).getServiceName());
System.out.println(((NamingEvent)event).getInstances());
}
});
NamingService
從官方示例可以了解到,對于我們使用者來說,NamingService是Nacos對外提供給使用者的接口,其實現類為com.alibaba.nacos.client.naming.NacosNamingService,歸納起來,NamingService提供了以下方法:
registerInstance:注冊實例。
deregisterInstance:注銷實例。
getAllInstances:獲取某一服務的所有實例。
selectInstances:獲取某一服務健康或不健康的實例。
selectOneHealthyInstance:根據權重選擇一個健康的實例。
getServerStatus:檢測服務端健康狀態。
subscribe:注冊對某個服務的監聽。
unsubscribe:注銷對某個服務的監聽。
getSubscribeServices:獲取被監聽的服務。
getServicesOfServer:獲取命名空間(namespace)下的所有服務名。【注:此方法有個小坑,參數pageNo要從1開始】
核心類
Naming Client的幾個核心類及其關系如下圖。我們分別來看一下這幾個類。
core-class
NacosNamingService
NacosNamingService是NamingService接口的實現類。實現了上面提到的那些方法。
此外,NacosNamingService還起到了初始化其他核心類的作用,因為對外提供的方法都是委托給其他核心類處理的。按順序將依次初始化EventDispatcher、NamingProxy、BeatReactor、HostReactor。
從NacosNamingService的構造函數我們也可以了解到,可以進行一些參數的自定義,總結如下(部分概念的含義可參考官方文檔):
EventDispatcher
EventDispatcher與其他事件分發的組件沒什么不同,用于處理subscribe、unsubscribe等等與服務監聽相關的方法,并分發NamingEvent到各Listener。
成員變量ConcurrentMap<String, List<EventListener>> observerMap保存了注冊的Listener,key為{服務名}@@{集群名},value為各個EventListener的列表。
EventDispatcher會啟動1個名為com.alibaba.nacos.naming.client.listener的線程用于處理事件的分發。
注意點:
分發NamingEvent時,按照subscribe(…)方法的調用順序串行依次調用EventListener的onEvent(…)方法。
調用subscribe(…)方法會引起對應Service的事件分發。
NamingProxy
NamingProxy用于與Nacos服務端通信,注冊服務、注銷服務、發送心跳等都經由NamingProxy來請求服務端。
NamingProxy會啟動1個名為com.alibaba.nacos.client.naming.serverlist.updater的線程,用于定期調用refreshSrvIfNeed()方法更新Nacos服務端地址,默認間隔為30秒,
對服務端API的調用將在后文總結。
注意點:refreshSrvIfNeed()方法對Nacos服務端地址的更新僅在使用endpoint的時候才會進行實際更新,如果是通過serverAddr配置的Nacos服務端地址,refreshSrvIfNeed()方法將不會進行任何操作。
BeatReactor
BeatReactor用于向Nacos服務端發送已注冊服務的心跳。
成員變量Map<String, BeatInfo> dom2Beat中保存了需要發送的BeatInfo,key為{serviceName}#{ip}#{port},value為對應的BeatInfo。
BeatReactor會啟動名為com.alibaba.nacos.naming.beat.sender的線程來發送心跳,默認線程數為1~CPU核心數的一半,可由namingClientBeatThreadCount參數指定。
默認情況下每5秒發送一次心跳,可根據Nacos服務端返回的clientBeatInterval的值調整心跳間隔。
注意點:0.8版本有一個小bug,客戶端心跳間隔并不受服務端返回值的控制。我已提交PR,預計將在0.9版本修復。
HostReactor
HostReactor用于獲取、保存、更新各Service實例信息。
成員變量Map<String, ServiceInfo> serviceInfoMap中保存了已獲取到的服務的信息,key為{服務名}@@{集群名}。
HostReactor會啟動名為com.alibaba.nacos.client.naming.updater的線程來更新服務信息,默認線程數為1~CPU核心數的一半,可由namingPollingThreadCount參數指定。定時任務UpdateTask會根據服務的cacheMillis值定時更新服務信息,默認值為10秒。該定時任務會在獲取某一服務信息時創建,保存在成員變量Map<String, ScheduledFuture<?>> futureMap中。
其他
PushReceiver
PushReceiver用于接收Nacos服務端的推送,初始化時會創建DatagramSocket使用UDP的方式接收推送。會啟動1個名為com.alibaba.nacos.naming.push.receiver的線程。
FailoverReactor
用于故障轉移,會啟動1個名為com.alibaba.nacos.naming.failover的線程并定時讀取名為00-00—000-VIPSRV_FAILOVER_SWITCH-000—00-00的文件,內容為1時表示開啟,此時獲取服務信息時會返回FailoverReactor緩存的服務信息。
Balancer
根據服務實例的權重挑選一個實例,實現簡單的負載均衡。
DiskCache
用于服務信息的持久化。
Naming API
API匯總如下:
| Method | URI | 含義 |
|---|---|---|
| POST | /nacos/v1/ns/instance | 注冊實例 |
| DELETE | /nacos/v1/ns/instance | 注銷實例 |
| GET | /nacos/v1/ns/instance/list | 獲取實例列表 |
| PUT | /nacos/v1/ns/instance/beat | 發送心跳 |
| GET | /nacos/v1/ns/api/hello | Nacos服務端狀態 |
| GET | /nacos/v1/ns/service/list | 獲取所有服務名 |
參數列表及示例
注冊實例
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
| ip | 實例IP地址 | |
| port | 實例端口 | |
| weight | 權重 | 默認為1.0 |
| enable | 是否開啟 | 默認為true |
| healthy | 健康狀態 | 默認為true |
| metadata | 其他信息 | |
| serviceName | 服務名 | |
| clusterName | 集群名 | 默認為DEFAULT |
請求示例:http://localhost:8848/nacos/v1/ns/instance?metadata=%7B%7D&namespaceId=public&port=8888&enable=true&healthy=true&ip=11.11.11.11&clusterName=TEST1&weight=1.0&serviceName=nacos.test.3&encoding=UTF-8&
返回示例:ok
注銷實例
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
| ip | 實例IP地址 | |
| port | 實例端口 | |
| serviceName | 服務名 | |
| clusterName | 集群名 | 默認為DEFAULT |
請求示例:http://localhost:8848/nacos/v1/ns/instance?cluster=DEFAULT&serviceName=nacos.test.3&encoding=UTF-8&namespaceId=public&port=9999&ip=2.2.2.2&
返回示例:ok
獲取實例列表
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
| serviceName | 服務名 | |
| clusters | 集群名 | 默認為DEFAULT |
| udpPort | 監聽的UPD端口號 | 由PushReceiver創建 |
| clientIP | 客戶端IP | |
| healthyOnly | 是否只返回健康的實例 |
請求示例:http://localhost:8848/nacos/v1/ns/instance/list?healthyOnly=false&namespaceId=public&clientIP=172.16.20.114&serviceName=nacos.test.3&udpPort=53957&encoding=UTF-8&
返回示例:{“metadata”:{},”dom”:”nacos.test.3”,”cacheMillis”:10000,”useSpecifiedURL”:false,”hosts”:[{“valid”:true,”marked”:false,”metadata”:{},”instanceId”:”2.2.2.2#9999#DEFAULT#nacos.test.3”,”port”:9999,”ip”:”2.2.2.2”,”clusterName”:”DEFAULT”,”weight”:1.0,”serviceName”:”nacos.test.3”,”enabled”:true},{“valid”:true,”marked”:false,”metadata”:{},”instanceId”:”11.11.11.11#8888#TEST1#nacos.test.3”,”port”:8888,”ip”:”11.11.11.11”,”clusterName”:”TEST1”,”weight”:1.0,”serviceName”:”nacos.test.3”,”enabled”:true}],”checksum”:”bd1054e6afb8d10730d945d74c4ce4421550584589236”,”lastRefTime”:1550584589236,”env”:””,”clusters”:””}
發送心跳
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
| serviceName | 服務名 | |
| beat | BeatInfo的JSON字符串 |
BeatInfo對象結構如下,與Instance對象類似:
| field | 含義 | 備注 |
|---|---|---|
| port | 端口 | |
| ip | IP地址 | |
| weight | 權重 | |
| metadata | 其他信息 | |
| serviceName | 服務名 | |
| clusterName | 集群名 | |
| scheduled | 是否心跳中 | 這個是BeatReactor用來標識狀態的 |
請求示例:http://localhost:8848/nacos/v1/ns/instance/beat?beat=%7B%22cluster%22%3A%22DEFAULT%22%2C%22ip%22%3A%222.2.2.2%22%2C%22metadata%22%3A%7B%7D%2C%22port%22%3A9999%2C%22scheduled%22%3Atrue%2C%22serviceName%22%3A%22nacos.test.3%22%2C%22weight%22%3A1.0%7D&serviceName=nacos.test.3&encoding=UTF-8&namespaceId=public&
返回示例:{“clientBeatInterval”:5000}
Nacos服務端狀態
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
請求示例:http://localhost:8848/nacos/v1/ns/api/hello?encoding=UTF-8&namespaceId=public&
返回示例:{“msg”:”Hello! I am Nacos-Naming and healthy! total services: raft 2, local port:8848”}
獲取所有服務名
| key | 含義 | 備注 |
|---|---|---|
| namespaceId | 命名空間 | 默認為public |
| pageNo | 頁碼 | 注意從1開始 |
| pageSize | 返回數量 | |
| selector | 過濾器 |
請求示例:http://localhost:8848/nacos/v1/ns/service/list?pageSize=100&encoding=UTF-8&namespaceId=public&pageNo=0&
返回示例:{“count”:1,”doms”:[“nacos.test.3”]}
結語
Nacos服務發現的客戶端較為簡單,其他語言也可以參照其API來實現客戶端。如果對源碼實現感興趣,可以自己看下代碼。
原文地址:https://www.cnblogs.com/lykbk/p/werwerwer35434343434343.html
總結
以上是生活随笔為你收集整理的Nacos 解读:服务发现客户端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网红男孩“钟美美”考上重点高中:模仿老师
- 下一篇: 滞回比较器