nacos源码阅读目录
一.客户端注册服务源码(1.4.1版本)
主要流程
1.NacosAutoServiceRegistration.register()
2.NacosServiceRegistry.register()
3.NacosNamingService.registerInstance()
4.NamingProxy.registerService()
5.NamingProxy.reqApi()
流程源码阅读
1.NacosAutoServiceRegistration.register()
package com.alibaba.cloud.nacos.registry;
public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
@Override
protected void register() {
//判断是否是禁用
if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
log.debug("Registration disabled.");
return;
}
//判断端口是否小于0
if (this.registration.getPort() < 0) {
this.registration.setPort(getPort().get());
}
//这里调用的是AbstractAutoServiceRegistration register方法
super.register();
}
}
public abstract class AbstractAutoServiceRegistration<R extends Registration>
implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
protected void register() {
//这里serviceRegistry是NacosNamingService
this.serviceRegistry.register(getRegistration());
}
2.NacosNamingService.registerInstance()
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
//获取NamingService
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
//获取要注册的实例信息
Instance instance = getNacosInstanceFromRegistration(registration);
try {
//进行服务端注册(重点)
namingService.registerInstance(serviceId, group, instance);
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
instance.getIp(), instance.getPort());
}
catch (Exception e) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
// rethrow a RuntimeException if the registration is failed.
// issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
rethrowRuntimeException(e);
}
}
3.NacosNamingService.registerInstance()
//NacosNamingService初始化
private void init(Properties properties) throws NacosException {
ValidatorUtils.checkInitParam(properties);
this.namespace = InitUtils.initNamespaceForNaming(properties);
InitUtils.initSerialization();
initServerAddr(properties);
InitUtils.initWebRootContext(properties);
initCacheDir();
initLogName(properties);
//初始化一个serverProxy 主要用于与服务端交互 发起http请求(@1)
this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList, properties);
//处理心跳的处理器(@2)
this.beatReactor = new BeatReactor(this.serverProxy, initClientBeatThreadCount(properties));
//处理服务更新的处理器(@3 )
this.hostReactor = new HostReactor(this.serverProxy, beatReactor, this.cacheDir, isLoadCacheAtStart(properties),
isPushEmptyProtect(properties), initPollingThreadCount(properties));
}
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
//检查一些不合理的设置
NamingUtils.checkInstanceIsLegal(instance);
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
//判断实例是否是临时的
if (instance.isEphemeral()) {
//构建心跳需要的信息
BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
//开启心跳实例线程(@2)
beatReactor.addBeatInfo(groupedServiceName, beatInfo);
}
//构建请求信息并发送注册请求
serverProxy.registerService(groupedServiceName, groupName, instance);
}
4.NamingProxy.registerService()
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
instance);
//构建请求信息
final Map<String, String> params = new HashMap<String, String>(16);
params.put(CommonParams.NAMESPACE_ID, namespaceId);
params.put(CommonParams.SERVICE_NAME, serviceName);
params.put(CommonParams.GROUP_NAME, groupName);
params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
params.put("ip", instance.getIp());
params.put("port", String.valueOf(instance.getPort()));
params.put("weight", String.valueOf(instance.getWeight()));
params.put("enable", String.valueOf(instance.isEnabled()));
params.put("healthy", String.valueOf(instance.isHealthy()));
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
//发起请求
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
}
5.NamingProxy.reqApi()
//这封装了对服务端请求的方法
public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers,
String method) throws NacosException {
params.put(CommonParams.NAMESPACE_ID, getNamespaceId());
if (CollectionUtils.isEmpty(servers) && StringUtils.isBlank(nacosDomain)) {
throw new NacosException(NacosException.INVALID_PARAM, "no server available");
}
NacosException exception = new NacosException();
if (StringUtils.isNotBlank(nacosDomain)) {
for (int i = 0; i < maxRetry; i++) {
try {
return callServer(api, params, body, nacosDomain, method);
} catch (NacosException e) {
exception = e;
if (NAMING_LOGGER.isDebugEnabled()) {
NAMING_LOGGER.debug("request {} failed.", nacosDomain, e);
}
}
}
} else {
Random random = new Random(System.currentTimeMillis());
int index = random.nextInt(servers.size());
for (int i = 0; i < servers.size(); i++) {
String server = servers.get(index);
try {
return callServer(api, params, body, server, method);
} catch (NacosException e) {
exception = e;
if (NAMING_LOGGER.isDebugEnabled()) {
NAMING_LOGGER.debug("request {} failed.", server, e);
}
}
index = (index + 1) % servers.size();
}
}
NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", api, servers, exception.getErrCode(),
exception.getErrMsg());
throw new NacosException(exception.getErrCode(),
"failed to req API:" + api + " after all servers(" + servers + ") tried: " + exception.getMessage());
}
二.服务端注册服务源码(2.0.2)
主要流程
服务端中有几个重要的类:Service、Client、ServiceManager、ClientManager.。
这几个类涉及管理服务的实体,注册服务接口,注销服务接口,心跳接口都是对这几个类进行操作。
ClientManager启动一个定时任务线程,对过期的服务进行清除
package com.alibaba.nacos.naming.controllers;
import static com.alibaba.nacos.naming.misc.UtilsAndCommons.DEFAULT_CLUSTER_NAME;
/**
* Instance operation controller.
*
* @author nkorange
*/
@RestController
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)
public class InstanceController {
@Autowired
private SwitchDomain switchDomain;
@Autowired
private InstanceOperatorClientImpl instanceServiceV2;
@Autowired
private InstanceOperatorServiceImpl instanceServiceV1;
@Autowired
private UpgradeJudgement upgradeJudgement;
/**
* Register new instance.
*
* @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 {
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);
//从request中获取实例信息z主要包括ip,port,服务名,group等信息
final Instance instance = parseInstance(request);
getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
return "ok";
}
}
//这个方法是上面的getInstanceOperator().registerInstance(namespaceId, serviceName, instance)
public void registerInstance(String namespaceId, String serviceName, Instance instance) {
boolean ephemeral = instance.isEphemeral();
//获取clientId(规则:ip:port#ephemeral 如192.168.9.145:8888#true)
String clientId = IpPortBasedClient.getClientId(instance.toInetAddr(), ephemeral);
//不存在该客户端则创建
createIpPortClientIfAbsent(clientId, ephemeral);
//创建一个service
Service service = getService(namespaceId, serviceName, ephemeral);
//注册实例
clientOperationService.registerInstance(service, instance, clientId);
}
//下面是 clientOperationService.registerInstance(service, instance, clientId);
//是EphemeralClientOperationServiceImpl实现类
public void registerInstance(Service service, Instance instance, String clientId) {
//如果service不存在则放到ServiceManager里,存在则返回存在的service(Service 重写了 equals方法)
Service singleton = ServiceManager.getInstance().getSingleton(service);
//从clientManager获取相应的client
Client client = clientManager.getClient(clientId);
//根据instance(前端参数) 构建InstancePublishInfo(要注册的实例 包含: ip、port、healthy、cluster)
InstancePublishInfo instanceInfo = getPublishInfo(instance);
//将服务实例添加到client
client.addServiceInstance(singleton, instanceInfo);
client.setLastUpdatedTime();
//发布客户端注册事件
NotifyCenter.publishEvent(new ClientOperationEvent.ClientRegisterServiceEvent(singleton, clientId));
NotifyCenter
.publishEvent(new MetadataEvent.InstanceMetadataEvent(singleton, instanceInfo.getMetadataId(), false));
//EphemeralIpPortClientManager 是ClientManager实现类 是对临时的服务进行管理,naocs默认是临时服务 重点看一下清理服务的方法 默认没有心跳90s的服务会被清掉
public EphemeralIpPortClientManager(DistroMapper distroMapper, SwitchDomain switchDomain) {
this.distroMapper = distroMapper;
//开启清除过期的客户端的线程 每5s执行一次
GlobalExecutor.scheduleExpiredClientCleaner(new ExpiredClientCleaner(this, switchDomain), 0,
Constants.DEFAULT_HEART_BEAT_INTERVAL, TimeUnit.MILLISECONDS);
clientFactory = ClientFactoryHolder.getInstance().findClientFactory(ClientConstants.EPHEMERAL_IP_PORT);
}
}