注册一个实例到服务。
POST
/nacos/v1/ns/instance
名称 | 类型 | 是否必选 | 描述 |
---|---|---|---|
ip | 字符串 | 是 | 服务实例IP |
port | int | 是 | 服务实例port |
serviceName | 字符串 | 是 | 服务名 |
namespaceId | 字符串 | 否 | 命名空间ID |
weight | double | 否 | 权重 |
enabled | boolean | 否 | 是否上线 |
healthy | boolean | 否 | 是否健康 |
metadata | 字符串 | 否 | 扩展信息 |
clusterName | 字符串 | 否 | 集群名 |
groupName | 字符串 | 否 | 分组名 |
ephemeral | boolean | 否 | 是否临时实例 |
错误代码 | 描述 | 语义 |
---|---|---|
400 | Bad Request | 客户端请求中的语法错误 |
403 | Forbidden | 没有权限 |
404 | Not Found | 无法找到资源 |
500 | Internal Server Error | 服务器内部错误 |
200 | OK | 正常 |
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=nacos.test.3&encoding=GBK&namespaceId=n1'
ok
实例注册HTTP接口:
/** * Register new instance. * 通过HTTP请求注册一个实例 * @param request http request * @return 'ok' if success * @throws Exception any error during register */
@CanDistro
@PostMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {
//获取参数中携带的命名空间id,未填则默认public
final String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
//获取实例注册的服务名,必填项
final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
//校验服务名合法性,Nacos设计的规则:groupName@@serviceName
NamingUtils.checkServiceNameFormat(serviceName);
//将请求中携带的参数信息包装成为Instance实例
final Instance instance = parseInstance(request);
//将该服务名节点的实例信息注册进命名空间中
serviceManager.registerInstance(namespaceId, serviceName, instance);
return "ok";
}
服务管理类
/** * 服务管理类中以一个Map持有了集群中所有的服务 * Map(namespace, Map(group::serviceName, Service)). */
private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
/** * Register an instance to a service in AP mode. * 使用AP模式(舍弃强一致性而保证系统的分区容错性和可用性的场景)注册实例 * <p>This method creates service or cluster silently if they don't exist. * * @param namespaceId id of namespace * @param serviceName service name * @param instance instance to register * @throws Exception any error occurred in the process */
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
//先判断服务是否存在,如果不存在则创建一个新的
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
//根据命名空间及服务名获取服务
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
//把当前实例添加进服务列表
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
/** * Add instance to service. * * @param namespaceId namespace * @param serviceName service name * @param ephemeral whether instance is ephemeral * @param ips instances * @throws NacosException nacos exception */
public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips)
throws NacosException {
//根据节点属性构建服务的key
//临时节点 com.alibaba.nacos.naming.iplist.ephemeral.${namespaceId}##${serviceName}
//持久化节点 com.alibaba.nacos.naming.iplist.${namespaceId}##${serviceName}
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
Service service = getService(namespaceId, serviceName);
synchronized (service) {
//将当前实例加入到所属服务名的实例列表中
List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
//将最新的实例列表通过一致性服务更新所属服务(该一致性服务只是一个代理服务),
//consistencyService会根据key的命名规则去选取实际服务
//临时节点的一致性服务(Distro-AP模式),持久化节点的一致性服务(Raft-CP模式)
consistencyService.put(key, instances);
}
}
@Override
public void put(String key, Record value) throws NacosException {
//保存服务
onPut(key, value);
//同步事件
distroProtocol.sync(new DistroKey(key, KeyBuilder.INSTANCE_LIST_KEY_PREFIX),DataOperation.CHANGE,globalConfig.getTaskDispatchPeriod() / 2);
}
/** * Put a new record. * * @param key key of record * @param value record */
public void onPut(String key, Record value) {
//临时节点,存储服务到DataStore的dataMap中
if (KeyBuilder.matchEphemeralInstanceListKey(key)) {
Datum<Instances> datum = new Datum<>();
datum.value = (Instances) value;
datum.key = key;
datum.timestamp.incrementAndGet();
dataStore.put(key, datum);
}
if (!listeners.containsKey(key)) {
return;
}
//发送实例变更通知
notifier.addTask(key, DataOperation.CHANGE);
}
//持有一个map
private Map<String, Datum> dataMap = new ConcurrentHashMap<>(1024);
//map结构保存服务在内存中
public void put(String key, Datum value) {
dataMap.put(key, value);
}
调用该HTTP接口是否就完成了实例的注册?(默认实例类型:临时实例)
答:是也不是。说是因为此接口的确完成了服务的创建与实例的注册。说不是又因为该实例昙花一现,因为任何一个服务注册中心都具有检活功能,如果单单调用这个接口我们会发现这个实例在控制台上15秒钟之后状态会变为不健康,30秒之后不可用实例自动下线。它来了,但是30秒之后他又走了!
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/lr309283175/article/details/115465789
内容来源于网络,如有侵权,请联系作者删除!