Nacos指南-服务发现:CMDB功能解析
上文分析创建服务时,我们发现有个访问策略的参数,下面我们就一起探索一下访问策略怎么玩的
| 名称 | 类型 | 是否必选 | 描述 |
|---|---|---|---|
| selector | JSON格式字符串 | 否 | 访问策略 |
在Nacos控制台上对应的配置名称为服务路由类型。除了默认值之外还可以选择标签类型,通过上文分析selector的格式为:
{"type": "label","expression": "CONSUMER.label.myLabel=PROVIDER.label.myLabel"}

若选择标签模式,表达式可以使用如下格式填写(必须以"CONSUMER.label."开始):
例:
CONSUMER.label.region=PROVIDER.label.region
此处我使用 region 作为标签。
CMDB_DATA_TABLE
| ip | region |
|---|---|
| 10.10.10.10 | shanghai |
| 11.11.11.11 | shanghai |
| 20.20.20.20 | beijing |
| 21.21.21.21 | beijing |
可以看出来
ip为 10.10.10.10,11.11.11.11 的归属地是上海
ip为 20.20.20.20,21.21.21.21 的归属地是北京
如果我们此时在上海,同城网络请求的耗时假设10ms,若访问北京服务器网络耗时假设30ms。若是我们在微服务调用的时候,同城网络只调用同城服务器是否就大大的提高了网络请求的效率?
先直接上结果:
先注册4个实例
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?port=8848&healthy=true&ip=10.10.10.10&weight=1.0&serviceName=spring-cloud-demo&encoding=GBK'curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?port=8848&healthy=true&ip=11.11.11.11&weight=1.0&serviceName=spring-cloud-demo&encoding=GBK'curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?port=8848&healthy=true&ip=20.20.20.20&weight=1.0&serviceName=spring-cloud-demo&encoding=GBK'curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?port=8848&healthy=true&ip=21.21.21.21&weight=1.0&serviceName=spring-cloud-demo&encoding=GBK'
此时服务名为spring-cloud-demo的4个实例已经全部注册成功

此时请求实例列表
curl -X GET '127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=spring-cloud-demo'
返回的数据为:
{"hosts": [{"ip": "21.21.21.21","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "21.21.21.21#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true},{"ip": "20.20.20.20","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "20.20.20.20#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true},{"ip": "10.10.10.10","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "10.10.10.10#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true},{"ip": "11.11.11.11","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "11.11.11.11#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true}],"dom": "spring-cloud-demo","name": "DEFAULT_GROUP@@spring-cloud-demo","cacheMillis": 3000,"lastRefTime": 1619072167699,"checksum": "c1230e0a77527f4093389636e4f85ccf","useSpecifiedURL": false,"clusters": "","env": "","metadata": {}
}
我们知道,我们的客户端实例在获取所属服务列表的时候会将自身ip传入clientIP请求参数中(此处详见NamingProxy.queryList)
public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly) throws NacosException {Map<String, String> params = new HashMap(8);params.put("namespaceId", this.namespaceId);params.put("serviceName", serviceName);params.put("clusters", clusters);params.put("udpPort", String.valueOf(udpPort));//传入当前实例的ip地址params.put("clientIP", NetUtils.localIP());params.put("healthyOnly", String.valueOf(healthyOnly));return this.reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, "GET");}
下面我们模拟实例端10.10.10.10请求服务列表
curl -X GET '127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=spring-cloud-demo&clientIP=10.10.10.10'
返回的数据为:
{"hosts": [{"ip": "10.10.10.10","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "10.10.10.10#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true},{"ip": "11.11.11.11","port": 8848,"valid": true,"healthy": true,"marked": false,"instanceId": "11.11.11.11#8848#DEFAULT#DEFAULT_GROUP@@spring-cloud-demo","metadata": {},"enabled": true,"weight": 1.0,"clusterName": "DEFAULT","serviceName": "spring-cloud-demo","ephemeral": true}],"dom": "spring-cloud-demo","name": "DEFAULT_GROUP@@spring-cloud-demo","cacheMillis": 3000,"lastRefTime": 1619072800221,"checksum": "c1230e0a77527f4093389636e4f85ccf","useSpecifiedURL": false,"clusters": "","env": "","metadata": {}
}
以上已经实现了服务路由标签过滤。若未匹配到标签,则默认返回全部提供方。
看一下实现
首先实现com.alibaba.nacos.api.cmdb.spi.CmdbService接口,将自己的cmdb数据转化成nacos的数据格式。
public class MyCmdbServiceImpl implements CmdbService {public static final List<Map<String,String>> CMDB_DATA =new ArrayList<>();{/* CMDB_DATA_TABLE:模拟cmdb数据库数据* ip region* 10.10.10.10 shanghai* 11.11.11.11 shanghai* 20.20.20.20 beijing* 21.21.21.21 beijing*/Map<String,String> machine10=new HashMap<>();machine10.put("ip","10.10.10.10");machine10.put("region","shanghai");CMDB_DATA.add(machine10);Map<String,String> machine11=new HashMap<>();machine11.put("ip","11.11.11.11");machine11.put("region","shanghai");CMDB_DATA.add(machine11);Map<String,String> machine20=new HashMap<>();machine20.put("ip","20.20.20.20");machine20.put("region","beijing");CMDB_DATA.add(machine20);Map<String,String> machine21=new HashMap<>();machine21.put("ip","21.21.21.21");machine21.put("region","beijing");CMDB_DATA.add(machine21);}@Overridepublic Set<String> getLabelNames() {return parseKeySet();}private Set<String> parseKeySet(){Set<String> labelNames=new HashSet<>();CMDB_DATA.forEach(d->{labelNames.addAll(d.keySet());});return labelNames;}@Overridepublic Set<String> getEntityTypes() {return parseKeySet();}@Overridepublic Label getLabel(String labelName) {Label label=new Label();label.setName(labelName);label.setValues(new HashSet<>());CMDB_DATA.forEach(d->{label.getValues().add(d.get(labelName));});return label;}@Overridepublic String getLabelValue(String entityName, String entityType, String labelName) {return getEntity(entityName,entityType).getLabels().get(labelName);}@Overridepublic Map<String, String> getLabelValues(String entityName, String entityType) {return getEntity(entityName,entityType).getLabels();}@Overridepublic Map<String, Map<String, Entity>> getAllEntities() {Map<String, Map<String, Entity>> result=new HashMap<>();CMDB_DATA.forEach(d->{d.keySet().forEach(col->{if(!result.containsKey(col)){result.put(col,new HashMap<>());}Entity entity=new Entity();entity.setName(d.get(col));entity.setType(col);entity.setLabels(d);result.get(col).put(d.get(col),entity);});});return result;}@Overridepublic List<EntityEvent> getEntityEvents(long timestamp) {//此处是cmdb数据变更事件的实现,由于是模拟,所有没有实现。return null;}@Overridepublic Entity getEntity(String entityName, String entityType) {Map<String, Map<String, Entity>> allEntities = getAllEntities();return allEntities.get(entityType).get(entityName);}
}
开启Cmdb加载参数
nacos.cmdb.loadDataAtStart=true
将我们自己的实现引入Nacos,通过SPI机制加载。
在 resources/META-INF/services 目录下创建名为 com.alibaba.nacos.api.cmdb.spi.CmdbService 的文件,文件内容为实现类的全路径:com.alibaba.nacos.cmdb.spi.MyCmdbServiceImpl (此处是我本次实现的类路径,自己实现需要根据实际情况)。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
