Nacos可以分為服務(wù)發(fā)現(xiàn)(Naming)和配置管理(Config)兩塊,而從使用上來說,又可分為Nacos服務(wù)端和客戶端,第一篇先來聊下服務(wù)發(fā)現(xiàn)(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對外提供給使用者的接口,其實現(xiàn)類為com.alibaba.nacos.client.naming.NacosNamingService,歸納起來,NamingService提供了以下方法:
registerInstance:注冊實例。
deregisterInstance:注銷實例。
getAllInstances:獲取某一服務(wù)的所有實例。
selectInstances:獲取某一服務(wù)健康或不健康的實例。
selectOneHealthyInstance:根據(jù)權(quán)重選擇一個健康的實例。
getServerStatus:檢測服務(wù)端健康狀態(tài)。
subscribe:注冊對某個服務(wù)的監(jiān)聽。
unsubscribe:注銷對某個服務(wù)的監(jiān)聽。
getSubscribeServices:獲取被監(jiān)聽的服務(wù)。
getServicesOfServer:獲取命名空間(namespace)下的所有服務(wù)名?!咀ⅲ捍朔椒ㄓ袀€小坑,參數(shù)pageNo要從1開始】
核心類
Naming Client的幾個核心類及其關(guān)系如下圖。我們分別來看一下這幾個類。
core-class
NacosNamingService
NacosNamingService是NamingService接口的實現(xiàn)類。實現(xiàn)了上面提到的那些方法。
此外,NacosNamingService還起到了初始化其他核心類的作用,因為對外提供的方法都是委托給其他核心類處理的。按順序?qū)⒁来纬跏蓟疎ventDispatcher、NamingProxy、BeatReactor、HostReactor。
從NacosNamingService的構(gòu)造函數(shù)我們也可以了解到,可以進行一些參數(shù)的自定義,總結(jié)如下(部分概念的含義可參考官方文檔):
EventDispatcher
EventDispatcher與其他事件分發(fā)的組件沒什么不同,用于處理subscribe、unsubscribe等等與服務(wù)監(jiān)聽相關(guān)的方法,并分發(fā)NamingEvent到各Listener。
成員變量ConcurrentMap> observerMap保存了注冊的Listener,key為{服務(wù)名}@@{集群名},value為各個EventListener的列表。
EventDispatcher會啟動1個名為com.alibaba.nacos.naming.client.listener的線程用于處理事件的分發(fā)。
注意點:
分發(fā)NamingEvent時,按照subscribe(…)方法的調(diào)用順序串行依次調(diào)用EventListener的onEvent(…)方法。
調(diào)用subscribe(…)方法會引起對應(yīng)Service的事件分發(fā)。
NamingProxy
NamingProxy用于與Nacos服務(wù)端通信,注冊服務(wù)、注銷服務(wù)、發(fā)送心跳等都經(jīng)由NamingProxy來請求服務(wù)端。
NamingProxy會啟動1個名為com.alibaba.nacos.client.naming.serverlist.updater的線程,用于定期調(diào)用refreshSrvIfNeed()方法更新Nacos服務(wù)端地址,默認(rèn)間隔為30秒,
對服務(wù)端API的調(diào)用將在后文總結(jié)。
注意點:refreshSrvIfNeed()方法對Nacos服務(wù)端地址的更新僅在使用endpoint的時候才會進行實際更新,如果是通過serverAddr配置的Nacos服務(wù)端地址,refreshSrvIfNeed()方法將不會進行任何操作。
BeatReactor
BeatReactor用于向Nacos服務(wù)端發(fā)送已注冊服務(wù)的心跳。
成員變量Map dom2Beat中保存了需要發(fā)送的BeatInfo,key為{serviceName}#{ip}#{port},value為對應(yīng)的BeatInfo。
BeatReactor會啟動名為com.alibaba.nacos.naming.beat.sender的線程來發(fā)送心跳,默認(rèn)線程數(shù)為1~CPU核心數(shù)的一半,可由namingClientBeatThreadCount參數(shù)指定。
默認(rèn)情況下每5秒發(fā)送一次心跳,可根據(jù)Nacos服務(wù)端返回的clientBeatInterval的值調(diào)整心跳間隔。
注意點:0.8版本有一個小bug,客戶端心跳間隔并不受服務(wù)端返回值的控制。我已提交PR,預(yù)計將在0.9版本修復(fù)。
HostReactor
HostReactor用于獲取、保存、更新各Service實例信息。
成員變量Map serviceInfoMap中保存了已獲取到的服務(wù)的信息,key為{服務(wù)名}@@{集群名}。
HostReactor會啟動名為com.alibaba.nacos.client.naming.updater的線程來更新服務(wù)信息,默認(rèn)線程數(shù)為1~CPU核心數(shù)的一半,可由namingPollingThreadCount參數(shù)指定。定時任務(wù)UpdateTask會根據(jù)服務(wù)的cacheMillis值定時更新服務(wù)信息,默認(rèn)值為10秒。該定時任務(wù)會在獲取某一服務(wù)信息時創(chuàng)建,保存在成員變量Map> futureMap中。
其他
PushReceiver
PushReceiver用于接收Nacos服務(wù)端的推送,初始化時會創(chuàng)建DatagramSocket使用UDP的方式接收推送。會啟動1個名為com.alibaba.nacos.naming.push.receiver的線程。
FailoverReactor
用于故障轉(zhuǎn)移,會啟動1個名為com.alibaba.nacos.naming.failover的線程并定時讀取名為00-00—000-VIPSRV_FAILOVER_SWITCH-000—00-00的文件,內(nèi)容為1時表示開啟,此時獲取服務(wù)信息時會返回FailoverReactor緩存的服務(wù)信息。
Balancer
根據(jù)服務(wù)實例的權(quán)重挑選一個實例,實現(xiàn)簡單的負(fù)載均衡。
DiskCache
用于服務(wù)信息的持久化。
Naming API
API匯總?cè)缦拢?/p>
MethodURI含義
POST/nacos/v1/ns/instance注冊實例
DELETE/nacos/v1/ns/instance注銷實例
GET/nacos/v1/ns/instance/list獲取實例列表
PUT/nacos/v1/ns/instance/beat發(fā)送心跳
GET/nacos/v1/ns/api/helloNacos服務(wù)端狀態(tài)
GET/nacos/v1/ns/service/list獲取所有服務(wù)名
參數(shù)列表及示例
注冊實例
key含義備注
namespaceId命名空間默認(rèn)為public
ip實例IP地址?
port實例端口?
weight權(quán)重默認(rèn)為1.0
enable是否開啟默認(rèn)為true
healthy健康狀態(tài)默認(rèn)為true
metadata其他信息?
serviceName服務(wù)名?
clusterName集群名默認(rèn)為DEFAULT
返回示例:ok
注銷實例
key含義備注
namespaceId命名空間默認(rèn)為public
ip實例IP地址?
port實例端口?
serviceName服務(wù)名?
clusterName集群名默認(rèn)為DEFAULT
返回示例:ok
獲取實例列表
key含義備注
namespaceId命名空間默認(rèn)為public
serviceName服務(wù)名?
clusters集群名默認(rèn)為DEFAULT
udpPort監(jiān)聽的UPD端口號由PushReceiver創(chuàng)建
clientIP客戶端IP?
healthyOnly是否只返回健康的實例
返回示例:{“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”:””}
發(fā)送心跳
key含義備注
namespaceId命名空間默認(rèn)為public
serviceName服務(wù)名?
beatBeatInfo的JSON字符串
BeatInfo對象結(jié)構(gòu)如下,與Instance對象類似:
field含義備注
port端口?
ipIP地址?
weight權(quán)重?
metadata其他信息?
serviceName服務(wù)名?
clusterName集群名?
scheduled是否心跳中這個是BeatReactor用來標(biāo)識狀態(tài)的
返回示例:{“clientBeatInterval”:5000}
Nacos服務(wù)端狀態(tài)
key含義備注
namespaceId命名空間默認(rèn)為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”}
獲取所有服務(wù)名
key含義備注
namespaceId命名空間默認(rèn)為public
pageNo頁碼注意從1開始
pageSize返回數(shù)量?
selector過濾器
返回示例:{“count”:1,”doms”:[“nacos.test.3”]}
結(jié)語
Nacos服務(wù)發(fā)現(xiàn)的客戶端較為簡單,其他語言也可以參照其API來實現(xiàn)客戶端。如果對源碼實現(xiàn)感興趣,可以自己看下代碼。
原文地址:https://www.cnblogs.com/lykbk/p/werwerwer35434343434343.html