Nacos指南-服务发现:创建服务

x33g5p2x  于2021-12-20 转载在 其他  
字(3.0k)|赞(0)|评价(0)|浏览(370)

API

请求类型

POST

请求路径

/nacos/v1/ns/service

请求参数

名称类型是否必选描述
serviceName字符串服务名
groupName字符串分组名
namespaceId字符串命名空间ID
protectThreshold浮点数保护阈值,取值0到1,默认0
metadata字符串元数据
selectorJSON格式字符串访问策略

错误编码

错误代码描述语义
400Bad Request客户端请求中的语法错误
403Forbidden没有权限
404Not Found无法找到资源
500Internal Server Error服务器内部错误
200OK正常

示例请求

curl -X POST '127.0.0.1:8848/nacos/v1/ns/service?serviceName=nacos.test.2&metadata=k1%3dv1'

示例返回

ok

关键流程源码解析

ServiceController

/** * Create a new service. * 新建一个服务 * @param namespaceId namespace id * @param serviceName service name * @param protectThreshold protect threshold * @param metadata service metadata * @param selector selector * @return 'ok' if success * @throws Exception exception */
    @PostMapping
    @Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
    public String create(@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
            @RequestParam String serviceName, @RequestParam(required = false, defaultValue = "0.0F") float protectThreshold,
            @RequestParam(defaultValue = StringUtils.EMPTY) String metadata,
            @RequestParam(defaultValue = StringUtils.EMPTY) String selector) throws Exception {
        //检测是服务是否已创建
        if (serviceManager.getService(namespaceId, serviceName) != null) {
            throw new IllegalArgumentException("specified service already exists, serviceName : " + serviceName);
        }

        Map<String, String> metadataMap = new HashMap<>(16);
        if (StringUtils.isNotBlank(metadata)) {
            metadataMap = UtilsAndCommons.parseMetadata(metadata);
        }

        Service service = new Service(serviceName);
        service.setProtectThreshold(protectThreshold);
        service.setEnabled(true);
        service.setMetadata(metadataMap);
        //设置服务路由类型,默认为None,
		//可以选择标签,并设置匹配规则 格式为:{"type": "label","expression": "CONSUMER.label.myLabel=PROVIDER.label.myLabel"}
        service.setSelector(parseSelector(selector));
        service.setNamespaceId(namespaceId);
        service.setLastModifiedMillis(System.currentTimeMillis());
        service.recalculateChecksum();
        //服务名称以及集群规范性检查
        service.validate();
        //更新服务信息
        serviceManager.addOrReplaceService(service);

        return "ok";
    }
    private Selector parseSelector(String selectorJsonString) throws Exception {
        //若传入的字符串为空,返回默认类型
        if (StringUtils.isBlank(selectorJsonString)) {
            return new NoneSelector();
        }
        //{type: "label", expression: "CONSUMER.label.site=PROVIDER.label.site"}
        JsonNode selectorJson = JacksonUtils.toObj(URLDecoder.decode(selectorJsonString, "UTF-8"));
        switch (SelectorType.valueOf(selectorJson.get("type").asText())) {
            case none:
                return new NoneSelector();
            case label:
                String expression = selectorJson.get("expression").asText();
				//转化表达式标签,必须以CONSUMER.label.形式开始
                Set<String> labels = LabelSelector.parseExpression(expression);
                LabelSelector labelSelector = new LabelSelector();
                labelSelector.setExpression(expression);
                labelSelector.setLabels(labels);
                return labelSelector;
            default:
                throw new NacosException(NacosException.INVALID_PARAM, "not match any type of selector!");
        }
    }

总结

创建服务需要留意的地方就是服务路由类型可以选择标签模式,当选择标签时表达式必须以 CONSUMER.label. 开头,实际的标签可以自定义。可以结合自己公司的CMDB资源管理在查询实例列表时可以获取与表达式匹配的机房节点,该策略Nacos本身并没有实现,需要用户自己实现CmdbService配置匹配规则。具体实现此处不做描述。后续会专门写一篇案例实现。

相关文章