准备
使用分支:v2.x-develop
核心类
NacosNamingService:命名服务入口;
NamingGrpcClientProxy:Grpc模式下命名客户端的代理;
InstanceRequestHandler:服务端用来处理实例请求的类;
EphemeralClientOperationServiceImpl:服务端暂时的实例的相关操作类
源码解读
- 实例注册【客户端】
- example/src/main/java/com/alibaba/nacos/example/NamingExample.java
java
//创建命名服务
NamingService naming = NamingFactory.createNamingService(properties);
//实例注册
naming.registerInstance(INSTANCE_SERVICE_NAME, INSTANCE_IP, INSTANCE_PORT, INSTANCE_CLUSTER_NAME);//※开始注册
- client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
java
@Override
public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {
registerInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);//※设置使用默认组注册实例
}
@Override
public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName)
throws NacosException {
//将参数封装成实例
Instance instance = new Instance();
instance.setIp(ip);
instance.setPort(port);
instance.setWeight(1.0);
instance.setClusterName(clusterName);
registerInstance(serviceName, groupName, instance);//※开始注册
}
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
//校验实例
NamingUtils.checkInstanceIsLegal(instance);
checkAndStripGroupNamePrefix(instance, groupName);
clientProxy.registerService(serviceName, groupName, instance);//※开始注册
}
- client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java
java
@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
instance);
if (instance.isEphemeral()) {
//将实例注册成一个短暂的实例
registerServiceForEphemeral(serviceName, groupName, instance);
} else {
doRegisterServiceForPersistent(serviceName, groupName, instance);
}
}
private void registerServiceForEphemeral(String serviceName, String groupName, Instance instance)
throws NacosException {
//缓存实例
redoService.cacheInstanceForRedo(serviceName, groupName, instance);
//注册服务
doRegisterService(serviceName, groupName, instance);//※马上就就要开始调服务了
}
/**
* Execute register operation.
*
* @param serviceName name of service
* @param groupName group of service
* @param instance instance to register
* @throws NacosException nacos exception
*/
public void doRegisterService(String serviceName, String groupName, Instance instance) throws NacosException {
InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);//※真真的开始使用grpc调用服务端了。。。终于无了
//注册后的事情【将缓存的实例标记成注册成功】
redoService.instanceRegistered(serviceName, groupName);
}
en...其实后面还有但是我上一章已经写了grpc的源码逻辑,所以我就不写了nacos通讯方式学习《gRPC》
- 实例注销【客户端】
- example/src/main/java/com/alibaba/nacos/example/NamingExample.java
java
naming.deregisterInstance(INSTANCE_SERVICE_NAME, INSTANCE_IP, INSTANCE_PORT, INSTANCE_CLUSTER_NAME);//※开始注销实例
- client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
java
@Override
public void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {
deregisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);//※在默认组中注销实例
}
@Override
public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)
throws NacosException {
//将参数封装成实例
Instance instance = new Instance();
instance.setIp(ip);
instance.setPort(port);
instance.setClusterName(clusterName);
deregisterInstance(serviceName, groupName, instance);//※开始注销实例
}
@Override
public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {
//实例校验
NamingUtils.checkInstanceIsLegal(instance);
checkAndStripGroupNamePrefix(instance, groupName);
clientProxy.deregisterService(serviceName, groupName, instance);//※开始注销实例
}
- client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java
java
@Override
public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER
.info("[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}", namespaceId, serviceName,
instance);
if (instance.isEphemeral()) {//判断实例是否是短暂的
deregisterServiceForEphemeral(serviceName, groupName, instance);//※注销短暂的实例
} else {
doDeregisterServiceForPersistent(serviceName, groupName, instance);
}
}
private void deregisterServiceForEphemeral(String serviceName, String groupName, Instance instance)
throws NacosException {
String key = NamingUtils.getGroupedName(serviceName, groupName);
InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesByKey(key);
if (instanceRedoData instanceof BatchInstanceRedoData) {
List<Instance> instances = new ArrayList<>();
if (null != instance) {
instances.add(instance);
}
batchDeregisterService(serviceName, groupName, instances);
} else {
//缓存中的实例状态修改成注销中
redoService.instanceDeregister(serviceName, groupName);
//开始注销
doDeregisterService(serviceName, groupName, instance);//※马上就要注销了
}
}
/**
* Execute deregister operation.
*
* @param serviceName service name
* @param groupName group name
* @param instance instance
* @throws NacosException nacos exception
*/
public void doDeregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.DE_REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);//※真真的开始使用grpc调用服务端了。。。终于无了
//注销后的状态修改
redoService.instanceDeregistered(serviceName, groupName);
}
en...注册跟注销其实是一样的逻辑,只是代码不一样而已
ps一下:nacos通讯方式学习《gRPC》
- 实例注册【服务端】
- naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/InstanceRequestHandler.java
java
@Override
@TpsControl(pointName = "RemoteNamingInstanceRegisterDeregister", name = "RemoteNamingInstanceRegisterDeregister")
@Secured(action = ActionTypes.WRITE)
@ExtractorManager.Extractor(rpcExtractor = InstanceRequestParamExtractor.class)
public InstanceResponse handle(InstanceRequest request, RequestMeta meta) throws NacosException {
//将实例转成对应的服务对象
Service service = Service.newService(request.getNamespace(), request.getGroupName(), request.getServiceName(),
true);
InstanceUtil.setInstanceIdIfEmpty(request.getInstance(), service.getGroupedServiceName());
switch (request.getType()) {
case NamingRemoteConstants.REGISTER_INSTANCE:
return registerInstance(service, request, meta);//※接受到注册请求后开始注册实例
case NamingRemoteConstants.DE_REGISTER_INSTANCE:
return deregisterInstance(service, request, meta);
default:
throw new NacosException(NacosException.INVALID_PARAM,
String.format("Unsupported request type %s", request.getType()));
}
}
private InstanceResponse registerInstance(Service service, InstanceRequest request, RequestMeta meta)
throws NacosException {
clientOperationService.registerInstance(service, request.getInstance(), meta.getConnectionId());//※开始注册了
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, service.getNamespace(), service.getGroup(),
service.getName(), request.getInstance().getIp(), request.getInstance().getPort()));
return new InstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);
}
- naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java
java
@Override
public void registerInstance(Service service, Instance instance, String clientId) throws NacosException {
//校验实例
NamingUtils.checkInstanceIsLegal(instance);
//将服务对象记录到Map中,nacos管理页面的查询就是从这里来的(同时元数据也有这个数据的时候才展示)
Service singleton = ServiceManager.getInstance().getSingleton(service);
if (!singleton.isEphemeral()) {
throw new NacosRuntimeException(NacosException.INVALID_PARAM,
String.format("Current service %s is persistent service, can't register ephemeral instance.",
singleton.getGroupedServiceName()));
}
Client client = clientManager.getClient(clientId);
checkClientIsLegal(client, clientId);
InstancePublishInfo instanceInfo = getPublishInfo(instance);
client.addServiceInstance(singleton, instanceInfo);
client.setLastUpdatedTime();
client.recalculateRevision();
NotifyCenter.publishEvent(new ClientOperationEvent.ClientRegisterServiceEvent(singleton, clientId));
NotifyCenter
.publishEvent(new MetadataEvent.InstanceMetadataEvent(singleton, instanceInfo.getMetadataId(), false));//※触发元数据事件
}
- 实例注销【服务端】
- naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/InstanceRequestHandler.java
java
@Override
@TpsControl(pointName = "RemoteNamingInstanceRegisterDeregister", name = "RemoteNamingInstanceRegisterDeregister")
@Secured(action = ActionTypes.WRITE)
@ExtractorManager.Extractor(rpcExtractor = InstanceRequestParamExtractor.class)
public InstanceResponse handle(InstanceRequest request, RequestMeta meta) throws NacosException {
Service service = Service.newService(request.getNamespace(), request.getGroupName(), request.getServiceName(),
true);
InstanceUtil.setInstanceIdIfEmpty(request.getInstance(), service.getGroupedServiceName());
switch (request.getType()) {
case NamingRemoteConstants.REGISTER_INSTANCE:
return registerInstance(service, request, meta);
case NamingRemoteConstants.DE_REGISTER_INSTANCE:
return deregisterInstance(service, request, meta);//※开始注销实例
default:
throw new NacosException(NacosException.INVALID_PARAM,
String.format("Unsupported request type %s", request.getType()));
}
}
private InstanceResponse deregisterInstance(Service service, InstanceRequest request, RequestMeta meta) {
clientOperationService.deregisterInstance(service, request.getInstance(), meta.getConnectionId());//※开始注销实例
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, DeregisterInstanceReason.REQUEST,
service.getNamespace(), service.getGroup(), service.getName(), request.getInstance().getIp(),
request.getInstance().getPort()));
return new InstanceResponse(NamingRemoteConstants.DE_REGISTER_INSTANCE);
}
- naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java
java
@Override
public void deregisterInstance(Service service, Instance instance, String clientId) {
if (!ServiceManager.getInstance().containSingleton(service)) {
Loggers.SRV_LOG.warn("remove instance from non-exist service: {}", service);
return;
}
Service singleton = ServiceManager.getInstance().getSingleton(service);
Client client = clientManager.getClient(clientId);
checkClientIsLegal(client, clientId);
InstancePublishInfo removedInstance = client.removeServiceInstance(singleton);
client.setLastUpdatedTime();
client.recalculateRevision();
if (null != removedInstance) {
NotifyCenter.publishEvent(new ClientOperationEvent.ClientDeregisterServiceEvent(singleton, clientId));
NotifyCenter.publishEvent(
new MetadataEvent.InstanceMetadataEvent(singleton, removedInstance.getMetadataId(), true));//※触发元数据事件
}
}
一句话概括
现下只学到这里,只是注册与注销。跟这块相关的还需要接着扒拉,比如:数据如何持久化存储、事件怎么订阅通知、客户端的请求如何分配处理。