spring cloud nacos源码解析(2)实例注册的那些事
程序员文章站
2022-05-06 08:00:25
...
//客户端注册请求
@CanDistro
@PostMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {
//获取命名空间 key = namespaceId 默认值public
final String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
NamingUtils.checkServiceNameFormat(serviceName);
final Instance instance = parseInstance(request);
//兼容版本 2.0.0版本 使用instanceServiceV2
getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
return "ok";
public static String optional(final HttpServletRequest req, final String key, final String defaultValue) {
// 获取key 没有则返回默认值
if (!req.getParameterMap().containsKey(key) || req.getParameterMap().get(key)[0] == null) {
return defaultValue;
}
String value = req.getParameter(key);
if (StringUtils.isBlank(value)) {
return defaultValue;
}
//参数编码格式 默认utf-8
String encoding = req.getParameter(ENCODING_KEY);
return resolveValue(value, encoding);
}
// 获取参数报告
public static String required(final HttpServletRequest req, final String key) {
String value = req.getParameter(key);
//参数为空异异常
if (StringUtils.isEmpty(value)) {
throw new IllegalArgumentException("Param '" + key + "' is required.");
}
String encoding = req.getParameter(ENCODING_KEY);
return resolveValue(value, encoding);
}
/**
* check combineServiceName format. the serviceName can't be blank.
* <pre>
* serviceName = "@@"; the length = 0; illegal
* serviceName = "[email protected]@"; the length = 1; illegal
* serviceName = "@@serviceName"; the length = 2; illegal
* serviceName = "[email protected]@serviceName"; the length = 2; legal 分组@@服务名合法
* </pre>
*
* @param combineServiceName such as: [email protected]@serviceName
*/
public static void checkServiceNameFormat(String combineServiceName) {
String[] split = combineServiceName.split(Constants.SERVICE_INFO_SPLITER);
if (split.length <= 1) {
throw new IllegalArgumentException(
"Param 'serviceName' is illegal, it should be format as '[email protected]@serviceName'");
}
if (split[0].isEmpty()) {
throw new IllegalArgumentException("Param 'serviceName' is illegal, groupName can't be empty");
}
}
初始化实例
private Instance getIpAddress(HttpServletRequest request) {
String enabledString = WebUtils.optional(request, "enabled", StringUtils.EMPTY);
boolean enabled;
//是否启用
if (StringUtils.isBlank(enabledString)) {
enabled = BooleanUtils.toBoolean(WebUtils.optional(request, "enable", "true"));
} else {
enabled = BooleanUtils.toBoolean(enabledString);
}
//获取权重
String weight = WebUtils.optional(request, "weight", "1");
//是否健康
boolean healthy = BooleanUtils.toBoolean(WebUtils.optional(request, "healthy", "true"));
//获取基础实例
Instance instance = getBasicIpAddress(request);
instance.setWeight(Double.parseDouble(weight));
instance.setHealthy(healthy);
instance.setEnabled(enabled);
return instance;
}
private Instance getBasicIpAddress(HttpServletRequest request) {
//获取ip port
final String ip = WebUtils.required(request, "ip");
final String port = WebUtils.required(request, "port");
//客户名称 clusterName
String cluster = WebUtils.optional(request, CommonParams.CLUSTER_NAME, StringUtils.EMPTY);
if (StringUtils.isBlank(cluster)) {
//名称为空则获取cluster 没有则为default
cluster = WebUtils.optional(request, "cluster", UtilsAndCommons.DEFAULT_CLUSTER_NAME);
}
boolean ephemeral = BooleanUtils.toBoolean(
WebUtils.optional(request, "ephemeral", String.valueOf(switchDomain.isDefaultInstanceEphemeral())));
Instance instance = new Instance();
instance.setPort(Integer.parseInt(port));
instance.setIp(ip);
instance.setEphemeral(ephemeral);
instance.setClusterName(cluster);
return instance;
}
建立service(实例处理对象)
/**
* Register an instance to a service in AP mode.
*
* <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 {
// 不存在则创建 instance.isEphemeral()是否为临时 service true是 false不是
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
//获取服务消息
Service service = getService(namespaceId, serviceName);
//service 为空 创建异常
checkServiceIsNull(service, namespaceId, serviceName);
//实例存放 在服务中
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
/**
* Create service if not exist.
*
* @param namespaceId namespace
* @param serviceName service name
* @param local whether create service by local
* @param cluster cluster
* @throws NacosException nacos exception
*/
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
//重新计算checkSum
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
//存储初始化 初始化 创建健康检测定时任务
putServiceAndInit(service);
if (!local) {
//不是临时service 处理则持久化消息
addOrReplaceService(service);
}
}
}
// 更新service 实例化信息
public List<Instance> updateIpAddresses(Service service, String action, boolean ephemeral, Instance... ips)
throws NacosException {
Datum datum = consistencyService
.get(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), ephemeral));
List<Instance> currentIPs = service.allIPs(ephemeral);
Map<String, Instance> currentInstances = new HashMap<>(currentIPs.size());
Set<String> currentInstanceIds = Sets.newHashSet();
for (Instance instance : currentIPs) {
currentInstances.put(instance.toIpAddr(), instance);
currentInstanceIds.add(instance.getInstanceId());
}
Map<String, Instance> instanceMap;
if (datum != null && null != datum.value) {
instanceMap = setValid(((Instances) datum.value).getInstanceList(), currentInstances);
} else {
instanceMap = new HashMap<>(ips.length);
}
for (Instance instance : ips) {
if (!service.getClusterMap().containsKey(instance.getClusterName())) {
Cluster cluster = new Cluster(instance.getClusterName(), service);
cluster.init();
service.getClusterMap().put(instance.getClusterName(), cluster);
Loggers.SRV_LOG
.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
instance.getClusterName(), instance.toJson());
}
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
instanceMap.remove(instance.getDatumKey());
} else {
Instance oldInstance = instanceMap.get(instance.getDatumKey());
if (oldInstance != null) {
instance.setInstanceId(oldInstance.getInstanceId());
} else {
instance.setInstanceId(instance.generateInstanceId(currentInstanceIds));
}
instanceMap.put(instance.getDatumKey(), instance);
}
}
if (instanceMap.size() <= 0 && UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD.equals(action)) {
throw new IllegalArgumentException(
"ip list can not be empty, service: " + service.getName() + ", ip list: " + JacksonUtils
.toJson(instanceMap.values()));
}
return new ArrayList<>(instanceMap.values());
}
上一篇: Spring Cloud
下一篇: Spring Cloud