Nacos源码系列之服务注册(一)

一、前言

二、源码概览

在这里插入图片描述

address模块: 主要查询nacos集群中节点个数以及IP的列表。
api模块: 主要给客户端调用的api接口的抽象。
common模块: 主要是通用的工具包和字符串常量的定义。
client模块: 主要是对依赖api模块和common模块,对api的接口的实现,给nacos的客户端使用。
cmdb模块: 主要是操作的数据的存储在内存中,该模块提供一个查询数据标签的接口。
config模块: 主要是服务配置的管理, 提供api给客户端拉去配置信息,以及提供更新配置
的,客户端通过长轮询的更新配置信息.数据存储是mysql。
naming模块: 主要是作为服务注册中心的实现模块,具备服务的注册和服务发现的功能。
console模块: 主要是实现控制台的功能.具有权限校验、服务状态、健康检查等功能。
core模块: 主要是实现Spring的PropertySource的后置处理器,用于加载nacos的default的配置信息。
distribution模块: 主要是打包nacos-server的操作,使用maven-assembly-plugin进行自定义打包。

核心功能项目:

配置管理 ——nacos-config
服务注册与发现——nacos-naming

三、数据模型

在这里插入图片描述

四、服务领域模型

在这里插入图片描述
nacos服务基本分为这几个级别:Service、Cluster、Instance。如上图所示。

1、Model

下面就分别介绍下这三种实体类的重要参数,其中,pojo包下是基本定义,core包中的实体做了额外的扩展。

(1)Service

pojo下的Service

namespace+group+name

public class Service implements Serializable {
   
    
    private static final long serialVersionUID = -990509089519499344L;
    
    private final String namespace;
    
    private final String group;
    
    private final String name;
    
    //暂时的,短暂的
    private final boolean ephemeral;
    
    private final AtomicLong revision;
    
    private long lastUpdatedTime;

//如何判断两个service相同
    @Override
    public boolean equals(Object o) {
   
        if (this == o) {
   
            return true;
        }
        if (!(o instanceof Service)) {
   
            return false;
        }
        Service service = (Service) o;
        return namespace.equals(service.namespace) && group.equals(service.group) && name.equals(service.name);
    }
}

(2)Cluster

pojo包下

//属于哪个service
private String serviceName;

//默认端口
private int defaultPort = 80;

core包下

//实例集合
@JsonIgnore
private Set<Instance> persistentInstances = new HashSet<>();


@JsonIgnore
private Set<Instance> ephemeralInstances = new HashSet<>();

//name相同
public boolean equals(Object obj) {
   
    if (!(obj instanceof Cluster)) {
   
        return false;
    }
    
    return getName().equals(((Cluster) obj).getName());
}

//把check任务交给scheduleExecutor异步执行。
public void init() {
   
    if (inited) {
   
        return;
    }
    checkTask = new HealthCheckTask(this);
    
    HealthCheckReactor.scheduleCheck(checkTask);
    inited = true;
}

(3)Instance

  • ephemeral参数用来区分实例时暂时性的还是持久的。
  • 实例的唯一id instanceId 生成规则:simple和snowflake。默认为simple。
  • 为了方便查询,instance中冗余了serviceName、clusterName等。
/**
* unique id of this instance.
*/
private String instanceId;


/**
* instance ip.
*/
private String ip;


/**
* instance port.
*/
private int port;


/**
* instance weight.
*/
private double weight = 1.0D;


/**
* instance health status.
*/
private boolean healthy = true;


/**
* If instance is enabled to accept request.
*/
private boolean enabled = true;


/**
* If instance is ephemeral.
*
* @since 1.0.0
*/
private boolean ephemeral = true;


/**
* cluster information of instance.
*/
private String clusterName;


/**
* Service information of instance.
*/
private String serviceName;


/**
* user extended attributes.
*/
private Map<String, String> metadata = new HashMap<String, String>();


//生成唯一id,两种方式:simple、snowflake
public String generateInstanceId(Set<String> currentInstanceIds) {
   
    String instanceIdGenerator = getInstanceIdGenerator();
    if (Constants.SNOWFLAKE_INSTANCE_ID_GENERATOR.equalsIgnoreCase(instanceIdGenerator)) {
   
        return generateSnowflakeInstanceId(currentInstanceIds);
    } else {
   
        return generateInstanceId();
    }
}

雪花算法 SnowFlowerIdGenerator

public synchronized long nextId() {
   
    long currentMillis = currentTimeMillis();
    if (this.lastTime == currentMillis) {
   
        if (0L == (this.sequence = ++this.sequence & 4095L)) {
   
            currentMillis = this.waitUntilNextTime(currentMillis);
        }
    } else {
   
        this.sequence = 0L;
    }
    
    this.lastTime = currentMillis;
    
    if (logger.isDebugEnabled()) {
   
        logger.debug("{}-{}-{}", (new SimpleDateFormat(DATETIME_PATTERN)).format(new Date(this.lastTime)),
                workerId, this.sequence);
    }
    
    currentId = currentMillis - EPOCH << 22 | workerId << 12 | this.sequence;
    return currentId;
}

这里从几个核心功能开始介绍:

2、客户端-服务注册

说服务注册之前,先简单说下服务的创建。

(1)create service

NamingFactory提供了两种创建命名服务的方法,根据server list和Properties。

    public static NamingService createNamingService(String serverList) throws NacosException {
   
        try {
   
            Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
            Constructor constructor = driverImplClass.getConstructor(String.class);
            return (NamingService</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值