Adapt all openAPI in for InstanceController. (#4441)

* Adapt get instance detail openAPI

* Adapt list statuses openAPI

* Adapt patch instance API

* For checkstyle.
This commit is contained in:
杨翊 SionYang 2020-12-09 23:43:15 +08:00 committed by GitHub
parent 81762c9817
commit 93ef110998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 308 additions and 78 deletions

View File

@ -26,6 +26,7 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.InstanceOperatorClientImpl;
import com.alibaba.nacos.naming.core.InstancePatchObject;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.healthcheck.RsInfo;
@ -33,9 +34,9 @@ import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.misc.SwitchEntry;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.pojo.Subscriber;
import com.alibaba.nacos.naming.pojo.InstanceOperationContext;
import com.alibaba.nacos.naming.pojo.InstanceOperationInfo;
import com.alibaba.nacos.naming.pojo.Subscriber;
import com.alibaba.nacos.naming.push.ClientInfo;
import com.alibaba.nacos.naming.push.DataSource;
import com.alibaba.nacos.naming.push.PushService;
@ -173,8 +174,7 @@ public class InstanceController {
@PutMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String update(HttpServletRequest request) throws Exception {
String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
NamingUtils.checkServiceNameFormat(serviceName);
instanceService.updateInstance(namespaceId, serviceName, parseInstance(request));
@ -311,7 +311,6 @@ public class InstanceController {
@PatchMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String patch(HttpServletRequest request) throws Exception {
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
NamingUtils.checkServiceNameFormat(serviceName);
String ip = WebUtils.required(request, "ip");
@ -320,35 +319,29 @@ public class InstanceController {
if (StringUtils.isBlank(cluster)) {
cluster = WebUtils.optional(request, "cluster", UtilsAndCommons.DEFAULT_CLUSTER_NAME);
}
Instance instance = serviceManager.getInstance(namespaceId, serviceName, cluster, ip, Integer.parseInt(port));
if (instance == null) {
throw new IllegalArgumentException("instance not found");
}
InstancePatchObject patchObject = new InstancePatchObject(cluster, ip, Integer.parseInt(port));
String metadata = WebUtils.optional(request, "metadata", StringUtils.EMPTY);
if (StringUtils.isNotBlank(metadata)) {
instance.setMetadata(UtilsAndCommons.parseMetadata(metadata));
patchObject.setMetadata(UtilsAndCommons.parseMetadata(metadata));
}
String app = WebUtils.optional(request, "app", StringUtils.EMPTY);
if (StringUtils.isNotBlank(app)) {
instance.setApp(app);
patchObject.setApp(app);
}
String weight = WebUtils.optional(request, "weight", StringUtils.EMPTY);
if (StringUtils.isNotBlank(weight)) {
instance.setWeight(Double.parseDouble(weight));
patchObject.setWeight(Double.parseDouble(weight));
}
String healthy = WebUtils.optional(request, "healthy", StringUtils.EMPTY);
if (StringUtils.isNotBlank(healthy)) {
instance.setHealthy(BooleanUtils.toBoolean(healthy));
patchObject.setHealthy(BooleanUtils.toBoolean(healthy));
}
String enabledString = WebUtils.optional(request, "enabled", StringUtils.EMPTY);
if (StringUtils.isNotBlank(enabledString)) {
instance.setEnabled(BooleanUtils.toBoolean(enabledString));
patchObject.setEnabled(BooleanUtils.toBoolean(enabledString));
}
instance.setLastBeat(System.currentTimeMillis());
instance.validate();
serviceManager.updateInstance(namespaceId, serviceName, instance);
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
instanceService.patchInstance(namespaceId, serviceName, patchObject);
return "ok";
}
@ -403,22 +396,8 @@ public class InstanceController {
String ip = WebUtils.required(request, "ip");
int port = Integer.parseInt(WebUtils.required(request, "port"));
Service service = serviceManager.getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.NOT_FOUND, "no service " + serviceName + " found!");
}
List<String> clusters = new ArrayList<>();
clusters.add(cluster);
List<Instance> ips = service.allIPs(clusters);
if (ips == null || ips.isEmpty()) {
throw new NacosException(NacosException.NOT_FOUND,
"no ips found for cluster " + cluster + " in service " + serviceName);
}
for (Instance instance : ips) {
if (instance.getIp().equals(ip) && instance.getPort() == port) {
com.alibaba.nacos.api.naming.pojo.Instance instance = instanceService
.getInstance(namespaceId, serviceName, cluster, ip, port);
ObjectNode result = JacksonUtils.createEmptyJsonNode();
result.put("service", serviceName);
result.put("ip", ip);
@ -430,10 +409,6 @@ public class InstanceController {
result.set("metadata", JacksonUtils.transferToJsonNode(instance.getMetadata()));
return result;
}
}
throw new NacosException(NacosException.NOT_FOUND, "no matched ip found!");
}
/**
* Create a beat for instance.
@ -503,21 +478,15 @@ public class InstanceController {
serviceName = key;
}
NamingUtils.checkServiceNameFormat(serviceName);
Service service = serviceManager.getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.NOT_FOUND, "service: " + serviceName + " not found.");
}
List<Instance> ips = service.allIPs();
List<? extends com.alibaba.nacos.api.naming.pojo.Instance> ips = instanceService
.listAllInstances(namespaceId, serviceName);
ObjectNode result = JacksonUtils.createEmptyJsonNode();
ArrayNode ipArray = JacksonUtils.createEmptyArrayNode();
for (Instance ip : ips) {
ipArray.add(ip.toIpAddr() + "_" + ip.isHealthy());
for (com.alibaba.nacos.api.naming.pojo.Instance ip : ips) {
ipArray.add(ip.toInetAddr() + "_" + ip.isHealthy());
}
result.replace("ips", ipArray);
return result;
}

View File

@ -22,6 +22,8 @@ import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.naming.healthcheck.RsInfo;
import com.alibaba.nacos.naming.pojo.Subscriber;
import java.util.List;
/**
* Instance operator.
*
@ -53,6 +55,8 @@ public interface InstanceOperator {
* Update instance information. Due to the basic information can't be changed, so this update should only update
* metadata.
*
* <p>Update API will replace the whole metadata with new input instance.
*
* @param namespaceId namespace
* @param serviceName grouped service name group@@service
* @param instance instance
@ -60,6 +64,19 @@ public interface InstanceOperator {
*/
void updateInstance(String namespaceId, String serviceName, Instance instance) throws NacosException;
/**
* Patch update instance information. Due to the basic information can't be changed, so this update should only
* update metadata.
*
* <p>Patch update will only update variables in requests, the others will keep original value.
*
* @param namespaceId namespace
* @param serviceName grouped service name group@@service
* @param patchObject objects need to be patch
* @throws NacosException nacos exception when update failed
*/
void patchInstance(String namespaceId, String serviceName, InstancePatchObject patchObject) throws NacosException;
/**
* Get all instance of input service.
*
@ -74,6 +91,20 @@ public interface InstanceOperator {
ServiceInfo listInstance(String namespaceId, String serviceName, Subscriber subscriber, String cluster,
boolean healthOnly) throws Exception;
/**
* Get instance detail information.
*
* @param namespaceId namespace
* @param serviceName grouped service name group@@service
* @param cluster cluster of instance
* @param ip ip of instance
* @param port port of instance
* @return instance info
* @throws NacosException nacos exception during query
*/
Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port)
throws NacosException;
/**
* Handle beat request.
*
@ -100,4 +131,14 @@ public interface InstanceOperator {
* @return heart beat interval
*/
long getHeartBeatInterval(String namespaceId, String serviceName, String ip, int port, String cluster);
/**
* List all instances whatever status they are.
*
* @param namespaceId namespace
* @param serviceName grouped service name group@@service
* @return all instances
* @throws NacosException nacos exception during query
*/
List<? extends Instance> listAllInstances(String namespaceId, String serviceName) throws NacosException;
}

View File

@ -42,6 +42,8 @@ import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.pojo.Subscriber;
import com.alibaba.nacos.naming.utils.ServiceUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
/**
@ -66,7 +68,8 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
public InstanceOperatorClientImpl(ClientManagerDelegate clientManager,
ClientOperationService clientOperationService, ServiceStorage serviceStorage,
NamingMetadataOperateService metadataOperateService, NamingMetadataManager metadataManager, SwitchDomain switchDomain) {
NamingMetadataOperateService metadataOperateService, NamingMetadataManager metadataManager,
SwitchDomain switchDomain) {
this.clientManager = clientManager;
this.clientOperationService = clientOperationService;
this.serviceStorage = serviceStorage;
@ -82,9 +85,7 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
public void registerInstance(String namespaceId, String serviceName, Instance instance) {
String clientId = instance.toInetAddr();
createIpPortClientIfAbsent(clientId, instance.isEphemeral());
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped, instance.isEphemeral());
Service service = getService(namespaceId, serviceName, instance.isEphemeral());
clientOperationService.registerInstance(service, instance, clientId);
}
@ -95,17 +96,13 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
Loggers.SRV_LOG.warn("remove instance from non-exist client: {}", clientId);
return;
}
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped, instance.isEphemeral());
Service service = getService(namespaceId, serviceName, instance.isEphemeral());
clientOperationService.deregisterInstance(service, instance, clientId);
}
@Override
public void updateInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped, instance.isEphemeral());
Service service = getService(namespaceId, serviceName, instance.isEphemeral());
if (!ServiceManager.getInstance().containSingleton(service)) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + service);
@ -121,12 +118,43 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
return result;
}
@Override
public void patchInstance(String namespaceId, String serviceName, InstancePatchObject patchObject)
throws NacosException {
Service service = getService(namespaceId, serviceName, true);
Instance instance = getInstance(namespaceId, serviceName, patchObject.getCluster(), patchObject.getIp(),
patchObject.getPort());
String instanceId = instance.toInetAddr();
Optional<InstanceMetadata> instanceMetadata = metadataManager.getInstanceMetadata(service, instanceId);
InstanceMetadata newMetadata = instanceMetadata.map(this::cloneMetadata).orElseGet(InstanceMetadata::new);
mergeMetadata(newMetadata, patchObject);
metadataOperateService.updateInstanceMetadata(service, instanceId, newMetadata);
}
private InstanceMetadata cloneMetadata(InstanceMetadata instanceMetadata) {
InstanceMetadata result = new InstanceMetadata();
result.setExtendData(new HashMap<>(instanceMetadata.getExtendData()));
result.setWeight(instanceMetadata.getWeight());
result.setEnabled(instanceMetadata.isEnabled());
return result;
}
private void mergeMetadata(InstanceMetadata newMetadata, InstancePatchObject patchObject) {
if (null != patchObject.getMetadata()) {
newMetadata.setExtendData(new HashMap<>(patchObject.getMetadata()));
}
if (null != patchObject.getEnabled()) {
newMetadata.setEnabled(patchObject.getEnabled());
}
if (null != patchObject.getWeight()) {
newMetadata.setWeight(patchObject.getWeight());
}
}
@Override
public ServiceInfo listInstance(String namespaceId, String serviceName, Subscriber subscriber, String cluster,
boolean healthOnly) {
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped);
Service service = getService(namespaceId, serviceName, true);
if (null != subscriber) {
createIpPortClientIfAbsent(subscriber.getAddrStr(), true);
clientOperationService.subscribeService(service, subscriber, subscriber.getAddrStr());
@ -138,13 +166,28 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
return result;
}
@Override
public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port)
throws NacosException {
Service service = getService(namespaceId, serviceName, true);
ServiceInfo serviceInfo = serviceStorage.getData(service);
if (serviceInfo.getHosts().isEmpty()) {
throw new NacosException(NacosException.NOT_FOUND,
"no ips found for cluster " + cluster + " in service " + serviceName);
}
for (Instance each : serviceInfo.getHosts()) {
if (cluster.equals(each.getClusterName()) && ip.equals(each.getIp()) && port == each.getPort()) {
return each;
}
}
throw new NacosException(NacosException.NOT_FOUND, "no matched ip found!");
}
@Override
public int handleBeat(String namespaceId, String serviceName, String ip, int port, String cluster,
RsInfo clientBeat) throws NacosException {
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = getService(namespaceId, serviceName, true);
String clientId = ip + ":" + port;
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped);
IpPortBasedClient client = (IpPortBasedClient) clientManager.getClient(clientId);
if (null == client || !client.getAllPublishedService().contains(service)) {
if (null == clientBeat) {
@ -181,11 +224,10 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
@Override
public long getHeartBeatInterval(String namespaceId, String serviceName, String ip, int port, String cluster) {
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
Service service = Service.newService(namespaceId, groupName, serviceNameNoGrouped);
Service service = getService(namespaceId, serviceName, true);
Optional<InstanceMetadata> metadata = metadataManager.getInstanceMetadata(service, ip);
if (metadata.isPresent() && metadata.get().getExtendData().containsKey(PreservedMetadataKeys.HEART_BEAT_INTERVAL)) {
if (metadata.isPresent() && metadata.get().getExtendData()
.containsKey(PreservedMetadataKeys.HEART_BEAT_INTERVAL)) {
return ConvertUtils.toLong(metadata.get().getExtendData().get(PreservedMetadataKeys.HEART_BEAT_INTERVAL));
}
String clientId = ip + ":" + port;
@ -197,9 +239,21 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
return switchDomain.getClientBeatInterval();
}
@Override
public List<? extends Instance> listAllInstances(String namespaceId, String serviceName) throws NacosException {
Service service = getService(namespaceId, serviceName, true);
return serviceStorage.getData(service).getHosts();
}
private void createIpPortClientIfAbsent(String clientId, boolean ephemeral) {
if (!clientManager.allClientId().contains(clientId)) {
clientManager.clientConnected(new IpPortBasedClient(clientId, ephemeral));
}
}
private Service getService(String namespaceId, String serviceName, boolean ephemeral) {
String groupName = NamingUtils.getGroupName(serviceName);
String serviceNameNoGrouped = NamingUtils.getServiceName(serviceName);
return Service.newService(namespaceId, groupName, serviceNameNoGrouped, ephemeral);
}
}

View File

@ -106,6 +106,35 @@ public class InstanceOperatorServiceImpl implements InstanceOperator {
serviceManager.updateInstance(namespaceId, serviceName, coreInstance);
}
@Override
public void patchInstance(String namespaceId, String serviceName, InstancePatchObject patchObject)
throws NacosException {
com.alibaba.nacos.naming.core.Instance instance = serviceManager
.getInstance(namespaceId, serviceName, patchObject.getCluster(), patchObject.getIp(),
patchObject.getPort());
if (instance == null) {
throw new NacosException(NacosException.INVALID_PARAM, "instance not found");
}
if (null != patchObject.getMetadata()) {
instance.setMetadata(patchObject.getMetadata());
}
if (null != patchObject.getApp()) {
instance.setApp(patchObject.getApp());
}
if (null != patchObject.getEnabled()) {
instance.setEnabled(patchObject.getEnabled());
}
if (null != patchObject.getHealthy()) {
instance.setHealthy(patchObject.getHealthy());
}
if (null != patchObject.getApp()) {
instance.setApp(patchObject.getApp());
}
instance.setLastBeat(System.currentTimeMillis());
instance.validate();
serviceManager.updateInstance(namespaceId, serviceName, instance);
}
@Override
public ServiceInfo listInstance(String namespaceId, String serviceName, Subscriber subscriber, String cluster,
boolean healthOnly) throws Exception {
@ -202,6 +231,28 @@ public class InstanceOperatorServiceImpl implements InstanceOperator {
return result;
}
@Override
public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port)
throws NacosException {
Service service = serviceManager.getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.NOT_FOUND, "no service " + serviceName + " found!");
}
List<String> clusters = new ArrayList<>();
clusters.add(cluster);
List<com.alibaba.nacos.naming.core.Instance> ips = service.allIPs(clusters);
if (ips == null || ips.isEmpty()) {
throw new NacosException(NacosException.NOT_FOUND,
"no ips found for cluster " + cluster + " in service " + serviceName);
}
for (com.alibaba.nacos.naming.core.Instance each : ips) {
if (each.getIp().equals(ip) && each.getPort() == port) {
return each;
}
}
throw new NacosException(NacosException.NOT_FOUND, "no matched ip found!");
}
private void checkIfDisabled(Service service) throws Exception {
if (!service.getEnabled()) {
throw new Exception("service is disabled now.");
@ -260,4 +311,13 @@ public class InstanceOperatorServiceImpl implements InstanceOperator {
}
return switchDomain.getClientBeatInterval();
}
@Override
public List<? extends Instance> listAllInstances(String namespaceId, String serviceName) throws NacosException {
Service service = serviceManager.getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.NOT_FOUND, "service: " + serviceName + " not found.");
}
return service.allIPs();
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.core;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* Patch object for instance update. To save which variables will be update by {@link
* com.alibaba.nacos.naming.controllers.InstanceController#patch(HttpServletRequest)} API
*
* @author xiweng.yy
*/
public class InstancePatchObject {
private final String cluster;
private final String ip;
private final int port;
private Map<String, String> metadata;
private Double weight;
private Boolean healthy;
private Boolean enabled;
public InstancePatchObject(String cluster, String ip, int port) {
this.cluster = cluster;
this.ip = ip;
this.port = port;
}
/**
* Will be deprecated in 2.x.
*/
private String app;
public String getCluster() {
return cluster;
}
public String getIp() {
return ip;
}
public int getPort() {
return port;
}
public Map<String, String> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public Boolean getHealthy() {
return healthy;
}
public void setHealthy(Boolean healthy) {
this.healthy = healthy;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
}