跳到主要内容

· 阅读需 18 分钟

Nacos 是什么?

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,定位于一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。从 2018 年 7 月开始宣布开源以来,已经走过了第四个年头,在这四年里,备受广大开源用户欢迎,共收获23.3K的star数,10.3K的Fork数,在开源中国发布的 2021 年度 OSC 中国开源项目评选中,Nacos 被评为云原生领域人气指数 Top5 的项目,发布电子书《Nacos 架构与原理》6w+阅读,2w下载量,发布半年的时间里在阿里云藏经阁历史下载榜前十。Nacos 在社区共同的建设下不断成长,逐步的开始帮助用户解决实际问题,助力企业数字化转型,目前已经广泛的使用在国内的公司中,根据微服务领域调查问卷,Nacos 在注册配置中心领域已经成为国内首选,占有50%+国内市场份额,被头部企业广泛使用!

《2022中国开源发展蓝皮书》由中国开源软件推进联盟(COPU)牵头,联合中国开发者网络(CSDN)、北京开源创新委员会、开放原子开源基金会、中国电子信息产业发展研究院、中科院软件研究所等 85 家企业及行业机构、120 多位开源专家和志愿者共同协作编撰完成,旨在全面展现当前中国开源发展的全景图,为国家政府相关管理部门、科研院所、科技企业以及开源从业者提供更多的理论参考和数据支撑,进一步助力我国开源生态的蓬勃发展。

根据最近刚发布的《2022中国开源发展蓝皮书》报告中 Github中国项目活跃度TOP 20Nacos 排名全国第六,作为基础类型云原生中间件,能有如此活跃度是非常不容易的,在上一年度《2021中国开源发展蓝皮书》中,Nacos 排名全国第十,也表现 Nacos 不仅仅维持高的项目活跃度,而且项目关注度和活跃度还在逐步提高。

image.png image.png 同时阿里巴巴在国内企业中开源影响力排行第一,在《2022中国开源发展蓝皮书》中介绍:“阿里巴巴是国内参与开源技术生态建设的企业典范。自2011年至今,阿里累计开源项目超过3000个,代表性的项目包括龙蜥操作系统、Apache RocketMQ、Apache Dubbo、Spring Cloud Alibaba、 Nacos、Seata、PolarDB-X、PolarDB for PostgreSQL等”。 Nacos 是阿里巴巴微服务领域开源你项目活跃度排行第一,也得益于开源协作模式,并且在Nacos中有大量国内外知名公司的核心贡献者,其中也包含就职在腾讯、华为、小米等等知名企业的同学,也正是社区整体的贡献者和用户在帮助 Nacos 成长,让 Nacos 逐步完善生态,支持几乎所有主流语言,整合更多开源生态,也正是用户和社区贡献者让Nacos为企业数字化转型首选产品。

image.png

Nacos 使用上的3点重要建议

Nacos 版本选择

Nacos 经过4年的发展,目前在大版本演进上已经到了第二代 Nacos 架构,即 Nacos 2.x 版本,Nacos 2.x 版本是基于 Nacos 1.x 中用户反馈使用习惯以及产品演进方向而构建的产品能力,中间包含了比如一致性算法升级,对性能的 10 倍提升,以及支持插件化来满足社区的定制诉求。并且保障了很好的兼容性,在服务能力上 Nacos 2.x 是完全兼容 Nacos 1.x 的协议,也就是 Nacos 2.x 服务端是完全兼容Nacos 1.x的客户端。 image.png

在基本能力上,Nacos 2.x 一致性协议复用了阿里在该领域最佳实践,以长连接为基础,减低通信损耗,基于Distro协议原有协议进行升级,在存储模型、保活模型上进行了重构,并且用推送机制代替了之前的轮训机制,进一步提升了产品的高可用以及稳定性,整体也复用了阿里百万实例的基础模型,在CAP理论基础上,根据场景来去选择最适合的协议,贴合场景来平衡一致性、高可用以及分区容灾,做到服务发现以及配置管理每个场景下,都做到稳定性、高可用、高性能的保障。

image.png 在拓展能力上,Nacos 2.x版本开始支持插件化能力,基于插件化是更方便的支持用户各种场景,很多用户公司内部有完善的体系基于Nacos可以简单的改造就可以融合进入,在鉴权、配置加解密场景都可以做到按照用户需求进行定制,并且给出默认的开源实现供用户选择,加解密为例,开源给出的默认实现是基于AES,用户也可以进行自定义。并且目前数据库的插件已经在路上,后续还会在安全等更多方面支持可插拔的插件化能力。 image.png

Nacos 支持还能支持那些场景

Nacos基本核心能力是面向于整体分布式的服务注册与发现,以及分布式节点配置管理,使用领域可以说是非常广泛的,比较常用的包含,微服务领域、高可用领域、内容领域以及数据库领域等,目前在微服务领域Nacos基本能力使用最广,微服务领域定位在一站式解决了用户应用的寻址、流量、配置场景服务平台,在高可用领域Nacos积累了大量的经验,可以实现大量降级、容灾、多活的高可用场景,也可以支持内容分发以及数据库分库分表、主备切换等场景的基础能力,可以说分布式的场景下,基本都可以跟Nacos进行构建,也帮助业务后续拓展留足了准备。 image.png

Nacos 排查问题最佳实践

注册配置中心在分布式节点交互中起着重要的作用,在业务分布式场景出现问题的时候需要快速进行诊断,判断是否是注册配置中心出现了问题,还是业务层的问题。

image.png 在注册中心中,服务发现是业务排查问题第一优先级需要定位的,服务发现具体对应的就是服务地址数据是否同步到了业务节点上,那在Nacos场景上,推送记录就是最关键的一个特性能力,这部分能力可以通过Nacos日志查询到,目前Nacos社区已经开始计划设计事件中心来支撑这部分能力,为了更好的演示,这里也通过阿里云微服务引擎MSE展现一下白屏化的推送轨迹能力,用户可以通过服务名称或者客户端IP,进行查询变更的时间以及变更的内容,就可以快速明确当前注册中心是否存在问题,并且能帮住业务进一步定位具体原因。 image.png 在配置中心链路,同样存在第一时间定位的问题,这里也通过阿里云微服务引擎MSE的最佳实践,推送轨迹能力展现排查的思路,可以通过配置名称或者订阅者客户端IP进行查询配置的变更时间,以及推送时间,以及推送内容MD5值进行匹配。 image.png 并且在分布式配置管理领域,通过补全推送轨迹能力,加上已经支持的历史版本查询能力,可以帮助业务全流程的观测配置的生命周期。 image.png 关于注册配置中心排查问题的思路上,总结是两个重点,一是数据变更确认,二是快速确定关系并且进行恢复。大多数场景如果是业务变更引起的,一定要第一时间进行回顾变更,避免给业务带来问题。在稳定性要求比较高的领域,建议业务体系上面向1-5-10(故障1分钟发现,5分钟上线处理,10分钟恢复)建设稳定性,这部分也是比较通用的能力建设,这里就不进行详细拓展,后续有机会可以单独聊一下。

Nacos 规划

Nacos 已经经历了两个重要阶段,初创期和高速发展期,目前正处于被大规模使用的 Nacos 的第三阶段是成为基础设施,需要面向于基础设施进行演进,帮助企业数字化转型,深度的拥抱各个领域内的场景,并且更深度的帮助企业解决问题。Nacos 社区目前面向于第三阶段,开始筹备 Nacos 3.0 架构设计进行规划讨论,并且逐步开始进行落地。 目前针对 Nacos 3.0 的建设规划大图主要包含三部分,第一部分是开源品牌和社区的升级,主要是面向于社区建立更紧密的联系。第二部分是面向更多生态进行深度融合,包含K8S数据整合、以及多生态数据打通,第三部分是最基础的部分,产品能力升级,基于 Nacos2.x 的协议进行增强,并且支持统一控制面、多数据中心等基础能力,用于支撑 Nacos 3.0 生态建设以及品牌升级。 目前 Nacos 3.0 部分已经随着社区核心贡献者开展中,大多数还在规划阶段,后续会通过Github issues进行开放,随之会打上Nacos 3.0的标签,欢迎大家进行领取一起参与到Nacos 3.0的贡献。 image.png

参与开源建议

最后部分整合我个人意见,向没有参与过开源的同学给出一些参与开源的建议,首先我认为开源对于开发者以及社区贡献都是非常有益的,如果你有时间并且也想参与开源,那我建议你从以下四个步骤进行深入: 第一步找到自己感兴趣的方向,这个点比较重要,会影响你后续贡献的持久程度,当然这个也是在逐步摸索中的,不过如果对于方向确认好后,应对的产品列表选择就会比较明朗了,在这个步骤考虑兴趣是我首要建议的,其次我建议,也可以考虑当前项目一些详细信息,重点考虑是否能帮助个人把价值的放大,使用范围越广的项目就越能让你的贡献在社会价值放大,也正向会提高成就感。 第二步是熟悉项目和产品,找到了方向和项目之后,就可以开始着手熟悉当前产品的细节,熟悉当前项目的运营机制,以及面向于产品开始接触对应领域问题,领域问题最后会沉淀成为你对这个领域的经验。 第三步其实就可以贡献开源了,这一个步骤其实面向于前两步骤是可以适当提前并行做,关键是从小问题入手做起,这样可以帮助你在前两个步骤中更快的找到感觉,也能从小问题开始帮助他人,在社区中建立个人影响力。 第四步其实是水到渠成的,面向于活跃的社区,当你足够熟悉该领域该产品之后,有了足够的贡献,就会在开源中逐步主导社区的决策,也能在社区中帮助更多的人发展共建。 image.png 上边是对个人贡献开源产品流程建议,适用于大多数开源项目的贡献。额外在开源上我觉得Nacos是不错的选择,首先产品定位是比较基础,能帮助开发者沉淀更通用的领域能力,社区活跃度能保持全国第六,并且在微服务领域已经被广泛使用,能帮助个人很好的放大价值。 再就是Nacos的熟悉产品也会比较简单,Nacos.io 官网可以帮助你快速入门,也有Nacos电子书免费下载帮助你深度了解Nacos架构设计。贡献开源上可以从Nacos社区仓库中 good first issues开始,跟着产品演进的方向,从小事开始在社区中发声,最后在Nacos社区有很多核心模块需要主导者,并且在社区中成为核心贡献者有社区投票权利,主导未来Nacos发展方向,并且作为社区核心成员,会有很多线上线下分享的机会,帮助个人以及企业建立更多社会影响力。总之在开源领域其实只要你愿意熟悉,一定会有所收获,祝愿每一位开发者在自己喜欢的领域能做出你想要的产品。最后感谢Nacos开源社区每一位同学!

· 阅读需 14 分钟

一、背景

小米是从1.x版本开始使用Nacos,后来为了性能升级到了2.0.3版本,一直在开启双写的情况下运行稳定,动态的服务发现与分布式配置中心的能力也满足我们的预期,随着使用我们集群的体量越来越大,需要对集群进行扩容,但在实际操作过程中遇到了一些问题,这篇文章主要总结一下集群扩缩容中遇到问题的解决过程和集群扩缩容步骤。

二、集群扩缩容出现的问题

(一) 发现服务降级问题

我们在进行扩容的过程中发现新部署的节点和原有的一个节点的集群管理中的元数据出现了 readyToUpgrade: false,并且经过测试发现这两个节点无法使用2.x版本的SDK进行注册服务,但是可以使用1.x版本的SDK注册,说明原本2.0.3版本的服务端从功能上降级为了1.x版本。

(二) 服务降级的排查过程

查看管理后台集群管理元数据

我们发现在集群管理元数据出现readyToUpgrade: false,通过查看readyToUpgrade相关的源码发现:首次启动时,默认处于未升级状态,此时会开启一个定时任务,检查服务数量与实例数量是否与监控一致,并且是否当前不存在双写任务,如果条件满足则将 readyToUpgrade 字段设置成true,并且通知给其他集群。定时任务会定时判断是否所有实例都满足升级条件,如果满足,则执行升级操作。当我们进行扩容操作的时候,因为新节点刚部署的时候,老节点地址列表没有新节点,新节点是无法完成自动升级的,所以集群管理的节点元数据会出现 readyToUpgrade: false。

查看服务端日志

我们在非新节点的日志文件中发现了服务降级的相关日志。

2022-03-09 17:51:42,262 INFO Downgrade to 1.X

根据服务降级日志“Downgrade to 1.X”在代码中全局搜索找到了对应的类UpgradeJudgement。

经过分析UpgradeJudgement源码逻辑,只要满足如下其中一个条件便会出现服务降级:

  1. 版本信息存在,但是小于2.x。

只有手动通过操作部署低版本节点才可能出现该情况,该设计应该是为了防止升级后的集群有问题需要降级,利用该原理需要降级的时候,只要重新部署一个低版本的节点其他节点可自动降级。

  1. UpgradeJudgement收到MembersChangeEvent事件,但是member信息中版本为空。

老的版本的集群没有收集节点的版本信息,这里版本为空也降级是为了兼容这部分集群,我们之所以出现意料之外的降级也和这个直接相关。

关键源码:

public void onEvent(MembersChangeEvent event) {
if (!event.hasTriggers()) {
Loggers.SRV_LOG.info("Member change without no trigger. "
+ "It may be triggered by member lookup on startup. " + "Skip.");
return;
}
Loggers.SRV_LOG.info("member change, event: {}", event);
for (Member each : event.getTriggers()) {
Object versionStr = each.getExtendVal(MemberMetaDataConstants.VERSION);
// come from below 1.3.0
if (null == versionStr) {
checkAndDowngrade(false);
all20XVersion.set(false);
return;
}
Version version = VersionUtil.parseVersion(versionStr.toString());
if (version.getMajorVersion() < MAJOR_VERSION) {
checkAndDowngrade(version.getMinorVersion() >= MINOR_VERSION)
; all20XVersion.set(false);
return;
}
}
all20XVersion.set(true);
}

服务降级源码分析

MemberInfoReportTask每隔5秒调用其他节点的/cluster/report 接口上报自己的member数据。


class MemberInfoReportTask extends Task {

private final GenericType<RestResult<String>> reference = new GenericType<RestResult<String>>() {
};

private int cursor = 0;

@Override
protected void executeBody() {
List<Member> members = ServerMemberManager.this.allMembersWithoutSelf();

if (members.isEmpty()) {
return;
}

this.cursor = (this.cursor + 1) % members.size();
Member target = members.get(cursor);

Loggers.CLUSTER.debug("report the metadata to the node : {}", target.getAddress());

final String url = HttpUtils
.buildUrl(false, target.getAddress(), EnvUtil.getContextPath(), Commons.NACOS_CORE_CONTEXT,
"/cluster/report");

try {
Header header = Header.newInstance().addParam(Constants.NACOS_SERVER_HEADER, VersionUtils.version);
AuthHeaderUtil.addIdentityToHeader(header);
asyncRestTemplate
.post(url, header, Query.EMPTY, getSelf(), reference.getType(), new Callback<String>() {
@Override
public void onReceive(RestResult<String> result) {
if (result.getCode() == HttpStatus.NOT_IMPLEMENTED.value()
|| result.getCode() == HttpStatus.NOT_FOUND.value()) {
Loggers.CLUSTER
.warn("{} version is too low, it is recommended to upgrade the version : {}",
target, VersionUtils.version);
Member memberNew = null;
if (target.getExtendVal(MemberMetaDataConstants.VERSION) != null) {
memberNew = target.copy();
// Clean up remote version info.
// This value may still stay in extend info when remote server has been downgraded to old version.
memberNew.delExtendVal(MemberMetaDataConstants.VERSION);
memberNew.delExtendVal(MemberMetaDataConstants.READY_TO_UPGRADE);
Loggers.CLUSTER.warn("{} : Clean up version info,"
+ " target has been downgrade to old version.", memberNew);
}
if (target.getAbilities() != null
&& target.getAbilities().getRemoteAbility() != null && target.getAbilities()
.getRemoteAbility().isSupportRemoteConnection()) {
if (memberNew == null) {
memberNew = target.copy();
}
memberNew.getAbilities().getRemoteAbility().setSupportRemoteConnection(false);
Loggers.CLUSTER
.warn("{} : Clear support remote connection flag,target may rollback version ",
memberNew);
}
if (memberNew != null) {
update(memberNew);
}
return;
}
if (result.ok()) {
MemberUtil.onSuccess(ServerMemberManager.this, target);
} else {
Loggers.CLUSTER.warn("failed to report new info to target node : {}, result : {}",
target.getAddress(), result);
MemberUtil.onFail(ServerMemberManager.this, target);
}
}

@Override
public void onError(Throwable throwable) {
Loggers.CLUSTER.error("failed to report new info to target node : {}, error : {}",
target.getAddress(), ExceptionUtil.getAllExceptionMsg(throwable));
MemberUtil.onFail(ServerMemberManager.this, target, throwable);
}

@Override
public void onCancel() {

}
});
} catch (Throwable ex) {
Loggers.CLUSTER.error("failed to report new info to target node : {}, error : {}", target.getAddress(),
ExceptionUtil.getAllExceptionMsg(ex));
}
}

@Override
protected void after() {
GlobalExecutor.scheduleByCommon(this, 2_000L);
}
}

当调用失败时会执行MemberUtil的onFail方法

    public static void onFail(final ServerMemberManager manager, final Member member, Throwable ex) {
manager.getMemberAddressInfos().remove(member.getAddress());
final NodeState old = member.getState();
member.setState(NodeState.SUSPICIOUS);
member.setFailAccessCnt(member.getFailAccessCnt() + 1);
int maxFailAccessCnt = EnvUtil.getProperty(MEMBER_FAIL_ACCESS_CNT_PROPERTY, Integer.class, DEFAULT_MEMBER_FAIL_ACCESS_CNT);

// If the number of consecutive failures to access the target node reaches
// a maximum, or the link request is rejected, the state is directly down
if (member.getFailAccessCnt() > maxFailAccessCnt || StringUtils
.containsIgnoreCase(ex.getMessage(), TARGET_MEMBER_CONNECT_REFUSE_ERRMSG)) {
member.setState(NodeState.DOWN);
}
if (!Objects.equals(old, member.getState())) {
manager.notifyMemberChange(member);
}
}

在onFail方法中,会判断节点状态是否发生了改变,比如由UP变为SUSPICIOUS,如果发生了改变,则会执行manager.notifyMemberChange(member)。在前面复现降级的场景下,存在一个节点宕机,所以重启的节点report宕机节点时一定会触发MemberUtil的onFail方法的执行,而当前重启的节点持有的宕机节点状态默认是UP,当执行onFail时,会变成SUSPICIOUS,所以会执行manager.notifyMemberChange(member),发布MembersChangeEvent事件,由于这个事件是由宕机节点触发的,所以MembersChangeEvent事件中trigger的member版本号为null,UpgradeJudgement收到MembersChangeEvent事件,并且member信息中版本为空,根据第2点的结论,此时会触发当前节点降级

void notifyMemberChange(Member member) {
NotifyCenter.publishEvent(MembersChangeEvent.builder().trigger(member).members(allMembers()).build());
}

服务降级过程时序图

为了方便理解,画了如下简单的时序图,省略了一些return和异步执行

image_xiaomi_2022.jpg

为什么关闭双写后服务不会降级

前面已经提到,降级的必要条件是UpgradeJudgement收到MembersChangeEvent,关闭双写后,UpgradeJudgement会取消订阅MembersChangeEvent,并且将双写是否关闭的值通过jraft写入到磁盘,当服务启动时又会重新加载到内存从而取消订阅MembersChangeEvent。

private class DoubleWriteEnabledChecker extends Thread {

private volatile boolean stillCheck = true;

@Override
public void run() {
Loggers.SRV_LOG.info("Check whether close double write");
while (stillCheck) {
try {
TimeUnit.SECONDS.sleep(5);
stopDoubleWrite = !ApplicationUtils.getBean(SwitchDomain.class).isDoubleWriteEnabled();
if (stopDoubleWrite) {
upgradeJudgement.stopAll();
stillCheck = false;
}
} catch (Exception e) {
Loggers.SRV_LOG.error("Close double write failed ", e);
}
}
Loggers.SRV_LOG.info("Check double write closed");
}
}

本地复现服务降级

在本地以2.0.3版本启动三个节点(node1、node2、node3)的集群模式,等三个节点都运行稳定后,查看其中每个节点数据目录(${nacos.home}/data/upgrade.state)下的升级状态都为true,说明三个节点目前都是2.x版本的状态。此时关闭node3节点,重启node1节点,启动完成后,发现node1此时会发生服务降级。

服务降级排查结论

在2.0.3版本默认开启双写,只要nacos集群其中一个节点挂掉,剩余节点如果不将这个节点从地址列表中移除,只要重启便会出现服务降级;另外在并发部署的情况下,也有可能出现服务降级。 关闭双写会关闭运行中服务降级的入口,所以2.x服务运行稳定后一定要关闭双写,我们的服务之所以会降级也是因为运行后未关闭双写。

(三) 临时解决方案

由于我们的Nacos集群已经正常升级到了2.0.3,并且稳定运行了一段时间,已经有很多客户端在使用2.x的版本,节点出现降级会导致这部分客户端无法进行注册,所以无论在任何情况下,都不能出现服务降级,决定执行如下方案:

  1. 扩容时新节点启动完成后关闭双写,强制新节点升级到2.x版本。
  2. 暂时先将服务降级的方法代码逻辑删除,只打印日志。 代码改动如下:
private void checkAndDowngrade(boolean jraftFeature) {
Loggers.SRV_LOG.info("jraftFeature:{} ignore Downgrade to 1.X", jraftFeature);
}

(四) 社区解决方案

我们将服务降级的问题也反馈给Nacos PMC席翁,在社区Nacos2.1.0正式版中,已经默认关闭了兼容 1.X 服务端升级,所以只要不手动开启,2.x的Nacos不可能在出现服务降级的问题,后续我们也会逐步将所有共有集群升级到2.1.0版本。

关闭兼容1.x服务端升级的功能对应PR:https://github.com/alibaba/nacos/pull/8016

三、集群扩缩容推荐

扩缩容使用的运维接口

关闭双写 :

/nacos/v1/ns/operator/switchesentry=doubleWriteEnabled&value=false 

查看节点监控:

/nacos/v1/ns/upgrade/ops/metrics

(一) 集群扩容操作步骤

  1. 部署新节点。
  2. 关闭新节点双写,检查日志是否出现如下日志,如果naming-raft出现了如下日志,说明降级入口已自动关闭。
start to close old raft protocol!!!
  1. 通过metrics接口查看双写是否关闭成功
  2. 手动修改老节点集群配置文件 cluster.conf,无须重启。
  3. 使用metrics接口查看新节点数据是否与老节点一致。
  4. 测试新节点服务注册与发现,配置添加与查询等基本功能是否正常。

(二) 集群缩容操作步骤

  1. nginx 去掉待移除节点ip。
  2. 修改保留节点集群配置文件cluster.conf,无须重启,等待所有节点数据一致。
  3. 观察nginx日志,确保移除merger节点无流量。
  4. top待移除节点,检查保留节点状态,模拟注册验证。

若是操作机器降配,需要先停服,再停机器,不然可能出现raft数据压缩包有问题的情况。

(三) 扩缩容优化点

目前我们每次进行扩缩容都需要修改每个节点的cluster.conf文件,操作非常繁琐,其实nacos提供了nacos-address 组件,引入nacos-address组件后进行扩缩容时无须一台一台修改地址,只需要修改Nacos-adress服务中的地址即可,可大大提升扩缩容效率。

四、总结

1.x版本升级到2.1.0之前的版本并且运行稳定后,必须关闭双写。

新集群统一使用2.1.0版本进行部署,否则在一定的场景下可能出现服务降级导致部分节点不可用。

对于体量较大的集群,需要引入nacos-address组件管理集群节点,避免手动频繁手动修改文件导致的误操作提升扩缩容效率。

· 阅读需 7 分钟

欢迎在校同学们参与Nacos开源之夏,社区导师手把手让你的代码被社会广泛复用,来赚取最高12000奖金,可推荐入职/实习你心意公司,又拿钱又成长又有价值,你还等什么呢?报名马上截止,快来参与Nacos开源之夏。

开源之夏是什么?

开源之夏是由“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护,促进优秀开源软件社区的蓬勃发展,培养和发掘更多优秀的开发者。

活动联合国内外各大开源社区,针对重要开源软件的开发与维护提供项目任务,并面向全球高校学生开放报名。

学生可在本活动中自主选择感兴趣的项目任务进行申请,并在中选后获得该开源项目资深维护者(社区导师)亲自指导的机会,完成项目并贡献给社区后,参与学生还将获得开源之夏活动奖金和结项证书。

Nacos&开源之夏2022

Nacos被评为2021Github年度全国社区活跃度第六,Nacos开源产品定位是更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,用云原生方式解决分布式领域核心问题。

自2018年孵化并开源以来,共收获21.8K的star数,9.5K的Fork数,在开源中国发布的 2021 年度 OSC 中国开源项目评选中,Nacos 被评为云原生领域人气指数 Top5 的项目,发布电子书《Nacos 架构与原理》阅读量近10W+,现已被大量微服务架构的软件公司选型作为其服务注册与发现中心。目前在国内服务注册中心及配置管理领域中市场占有率排名第一

此次Nacos社区开放的题目中包含了Nacos第三代架构的部分核心功能模块,将直接参与社区的核心功能,欢迎进入Nacos开源之夏参与Nacos3.0的建设,为未来五年开源微服务发展奠定基础。

参与Nacos开源之夏条件

  • 本活动面向年满 18 周岁在校学生。
  • 暑期即将毕业的学生,只要在申请时学生证处在有效期内,就可以提交申请。
  • 海外学生可提供录取通知书、学生卡、在读证明等文件用于证明学生身份。

参与Nacos开源之夏,你能获得什么?

  1. 【你的代码被社会广泛复用】 你的代码可能会运行在上万家企业核心业务逻辑中,帮助企业解决问题。
  2. 【赢得最高12000奖金】 奖金总额根据项目难度分为进阶 12000 元、基础 8000 元(注:奖金数额为税前人民币金额)
  3. 【社区核心人员辅导快速成长】 只要你报名被选中,每个题目的导师会精心手把手教你融入社区,帮助你完成题目的设计以及最终的落地。
  4. 【推荐入职/实习】 在本次编程之夏项目中表现优秀同学,可推荐入职/实习 你心意的公司工作。
  5. 【额外获得社区礼包】 所有参与本次编程之夏项目的同学,均可获得Nacos社区大礼包。

百分百有奖品拿哦,现在唯一的问题是时间不多了,赶紧上车报名,截止报名时间是6月4日,6个核心题目,快点来报名参与Nacos编程之夏吧。

报名方式

点开Nacos开源之夏的链接 选择你喜欢的题目,Nacos社区围绕Nacos第三代架构精心计划了题目包含 “服务网格生态”、“多数据源建设”、“CoreDNS支持”、“K8S元数据同步”、“Nacos2.X建设”等技术方向展开。进行报名。

具体流程请参考学生指南 访问可能会比较慢,请多等一下.

请注意找导师沟通截止流程时间,优先更导师沟通,能帮助你更好的了解题目。

想要报名的同学,请用钉钉扫码加入Nacos开源之夏2022钉钉群,方便大家交流题目内容。 image.png

参考资料

Nacos Github:https://github.com/alibaba/nacos

Nacos 官网:http://nacos.io

为了让同学们更好地了解Nacos,我们提供了电子书 供大家阅读学习

对于微服务分布式事务有兴趣的同学,可以尝试填报团队维护的另一个重磅级开源项目--Seata 参与开源之夏.

· 阅读需 12 分钟

2.1.0

在社区和开源之夏的导师同学的共同努力下,2.1.0版本的主要目标已经基本完成,经过了近1个月的Beta测试后,在51劳动节,Nacos社区发布2.1.0版本作为给所有社区参与者的劳动节礼物。

新版本内容

2.1.0版本主要增加了认证插件和配置加密插件能力。 并关闭默认支持服务端从 1.X 版本升级的能力,若需要使用平滑升级能力,需要在配置文件中开启此功能。 对于客户端,此版本重构了类扫描逻辑并删除了 org.reflections 依赖,以解决 org.reflections 冲突时的不兼容问题。 最后,这个版本做了一些控制台优化并修复了 2.0.4 中发现的一些问题。 详细变更日志如下:

## Features

[#5695] Add a plugin SPI for configuration encryption and decryption for Nacos 2.0
[#5696] Add a plugin SPI for authentication for Nacos 2.0.
[#7930] Default close support upgrade from 1.X feature.
[#7992] Support cluster grpc client to set thread pool size.
[#8220] Add reset raft cluster operation.

## Enhancement & Refactor

[#7487] Add generics for the CacheBuilder.
[#7879] Refactor destroy method of AbstractMemberLookup.
[#7924][#8214] Add ldap auth plugin.
[#7952] Ignore read request for raft follower's state machine to enhance raft stability.
[#7966] Add more information in Auth/Distro/Curcuit-Filter when cause some server error.
[#7971] Stop version judge Task and release thread after upgrade completely.
[#8072] Enhance memory cost in DistroProtocol initialization.
[#8107] Enhance console change password operation.
[#8156] Support js and css of console auto-upgrade.


## BugFix

[#1717][#7359] Fix XSS vulnerabilities.
[#6273] Fix loop request for offline server nodes API.
[#6999] Fix Nacos client does not support logback overload log configuration.
[#7757] Fix jraft read request deserialize to write request problem.
[#7780] Fix config a-b-a problem.
[#7941] Fix version comparison error in Config Detail page.
[#8087] Fix text out of box in configuration manager.
[#8108] Fix throw NPR for health check for v2.
[#8050] Fix configuration about Distro changes could not take effect.
[#8161] Fix console can't use relative path problem.
[#8163] Fix multi-instance share the same local snapshot.
[#8196] Fix subscriber api without count when the query number is more than subscriber count.

## Dependency

[#7758] Update module nacos-consistency protobuf-maven-plugin version to 0.6.1.
[#7886] Enhance package scan logic and remove org.reflections dependency.

## Tests

[#4981] Add much unit test.
[#8009] Fix NPE of unit test.

插件化

支持插件化是2.1.0版本的主要改动之一。Nacos通过SPI 的方式,允许用户和开发者实现自己的对应功能插件使用;目前Nacos已经支持鉴权和加解密的插件化能力。

鉴权

自从Nacos 1.2 版本加入鉴权功能后,社区对鉴权功能的讨论一直持续。原因是Nacos目前的鉴权系统设计为防止错用及用户隔离。但社区中对鉴权能力的要求不局限于此,为了满足不同的用户对鉴权程度的不同要求。Nacos社区希望设计一套用于鉴权的API,并将其注入到网络请求的流程中。 Nacos目前的鉴权实现也已经重构成默认的鉴权插件,社区所贡献的LADP也已改造完成,使用方式和以前一致;如果需要开发自定义的鉴权插件,可以参考文档鉴权插件实现。

加解密

在Nacos社区中,许多用户关注配置中某些敏感信息的安全性问题。除了通过鉴权,社区也希望能对配置内容中的敏感信息进行加密。由于用户和开发者所使用或对接的算法和加解密系统可能不同,因此Nacos社区设计了一套用于加解密的API,并将其注入到发布和查询配置的工作流程中。 更多加解密插件的细节可以参考文档配置加密插件

默认关闭兼容1.X服务端升级

默认关闭支持服务端从 1.X 版本升级的能力是Nacos2.1.0版本的另一个重要改动。在2.0.X版本中,数据结构进行了一些重新设计,导致和1.X的数据无法直接兼容,为了方便社区用户从1.X平滑升级到Nacos2.0版本,Nacos2.0版本除了兼容1.X的openAPI外,还新增了双写数据等逻辑;但这部分逻辑对系统资源有较大的损耗,并且由于机制较为复杂,导致部分直接使用2.0版本的用户可能会遇到一些版本切换的疑问。因此在Nacos2.1版本中,我们默认关闭了兼容1.X服务端平滑升级能功能,关闭该功能后直接部署2.1版本将不会再从1.X模式进行检测和升级,而是直接运行在2.X的数据模式下,同时也支持2.0版本直接升级2.1版本。 若是希望从Nacos1.X直接升级到Nacos2.1.0版本,则需要在application.properties文件中设置配置nacos.core.support.upgrade.from.1x=true,此时Nacos2.1版本会和Nacos2.0版本一样,以1.X的数据模式启动,并开始自动升级检测,待全集群数据一致,且准备完毕后,切换至2.0数据模式,更多升级相关的内容,请参考文档升级文档

社区

在过去的一年里,社区内涌现出大量优秀的贡献者,他们为Nacos社区持续不断的注入活力和内容;正是有你们的关注和贡献,Nacos才能在2021年获得开源中国最受欢迎项目的奖项,在此郑重感谢去年参与社区贡献的Contributor,Committer和PMC同学,以及其他通过各种方式参与到社区的同学。 感谢同学们的持续贡献,正是有了大家的共同努力,Nacos才能变得越来越完善。 OSCHINA-Nacos.jpg

新PMC&Committer

Nacos社区新晋级了一位PMC同学和两位Committer同学。 来自滴滴出行的sanxun0325同学作为Nacos,Dubbo Go,Sentinal的Committer,在社区十分活跃,在过去的2021年也是为Nacos社区的go-sdk做出了大量贡献,并主导着Nacos-go-sdk社区的发展;因此提名为Nacos社区的PMC。

另外,来自微众银行MajorHe1和小米科技hujun-w-2同学,鉴于持续的大量社区贡献,经社区PMC及Committer的投票表决,提名为Nacos社区的Committer,希望二位能继续保持活跃,为Nacos社区添砖加瓦。

MajorHe1-committer.jpghujun-w-2-committer.jpg

年度优秀Committer

2021年度,Nacos社区有许多Committer利用自己的业余时间,持续的贡献者Nacos社区。为了感谢,Nacos社区评选出了12位2021年度优秀Committer,并特意制作了奖杯及卫衣,希望在2022年度,仍然能看到你们的身影。 这12位优秀Committer分别是(根据字母顺序):

没有被选中的Committer同学也不要担心,2022年度我们仍然会保持这个活动,希望2022年度优秀Committer有你们的名字。 2021-committer-rewards.JPG

贡献者激励活动

相信很多贡献者都已经收到了Nacos寄出的小礼物了,此类的活动Nacos社区会持续进行,只需要您持续关注社区,积极参与社区共建,就能够获得哦。 Nacos-cup.jpg

代码贡献活动

Nacos社区预计在7月会再次进行贡献者的激励活动,届时会统计并评选出数十位2022年7月前较为活跃的贡献者(不仅是Nacos的主干仓库,也包含了nacos-group下的各个仓库),并寄出新的社区纪念礼品;下期的贡献者礼品是雨伞,赶紧进行贡献获取吧。

优秀社区文章活动

Nacos社区的贡献并不只包含代码,社区也欢迎广大用户或开发者发表技术文章来和大家分享关于Nacos的技术心得;其中包括但不限于:Nacos的应用、源码解析、产品融合和社区合作等。欢迎大家提交文章到Nacos官方文档的博客栏目中,或发布在自己的微信公众号及博客中;对于优秀的社区文章,Nacos社区会收录到博客栏目及阿里开源的官方网站中,并会给文章作者寄送相应的礼物。

开源之夏2022

在2021年,Nacos社区参与了由ISCAS(中国科学院软件研究所)和openEuler社区托管的开源之夏2021活动,在导师、高校同学和主办方的共同努力下,完成了数个意义非凡的课题,其中就包括本次发版中最关键的两个改动:鉴权插件及配置加密插件。 今年,开源之夏2022如期而至,Nacos社区也再次参与活动,并制定了6个课题,欢迎关注开源之夏2022 ,参与Nacos的开源之夏2022。

About Nacos

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

· 阅读需 5 分钟

当前文档描述如何通过云原生应用管理平台 Rainbond 一键安装高可用 Nacos 集群。这种方式适合不太了解 Kubernetes、容器化等复杂技术的用户使用,降低了在 Kubernetes 中部署 Nacos 的门槛。

背景信息

Rainbond 与 Nacos 的结合

Rainbond 是一款易于使用的开源云原生应用管理平台。借助于它,用户可以在图形化界面中完成微服务的部署与运维。借助 Kubernetes 和容器化技术的能力,将故障自愈、弹性伸缩等自动化运维能力赋能给用户的业务。

Rainbond 内置原生 Service Mesh 微服务框架,同时与 Spring Cloud、Dubbo 等其他微服务框架也有很好的整合体验。故而大量的 Rainbond 用户也可能是 Nacos 微服务注册中心的用户。这类用户不必再关心如何部署 Nacos 集群,Rainbond 团队将 Nacos 制作成为可以一键部署的应用模版,供开源用户免费下载安装。这种安装方式极大的降低了用户使用 Nacos 集群的部署负担,目前支持 1.4.2 与 2.0.4 版本。

关于应用模版

应用模版是面向 Rainbond 云原生应用管理平台的安装包,用户可以基于它一键安装业务系统到自己的 Rainbond 中去。无论这个业务系统多么复杂,应用模版都会将其抽象成为一个应用,裹挟着应用内所有组件的镜像、配置信息以及所有组件之间的关联关系一并安装起来。

前提条件

  • 部署好的 Rainbond 云原生应用管理平台,快速体验版本 可以在个人 PC 环境中以启动一个容器的代价运行。

  • 互联网连接。

快速开始

  • 访问内置的开源应用商店

选择左侧的 应用市场 标签页,在页面中切换到 开源应用商店 标签页,搜索关键词 nacos 即可找到 Nacos-cluster 应用。

nacos-1

  • 一键安装

点击 Nacos-cluster 右侧的 安装 可以进入安装页面,填写简单的信息之后,点击 确定 即可开始安装,页面自动跳转到拓扑视图。

nacos-2

参数说明:

选择项说明
团队名称用户自建的工作空间,以命名空间隔离
集群名称选择 Nacos 被部署到哪一个 K8s 集群
选择应用选择 Nacos 被部署到哪一个应用,应用中包含有若干有关联的组件
应用版本选择 Nacos 的版本,目前可选版本为 1.4.2、2.0.4

等待几分钟后,Nacos 集群就会安装完成,并运行起来。

nacos-3

  • 测试

需要执行服务注册的其他微服务组件,可以在建立面向 Nacos 的依赖关系后,使用 ${NACOS_HOST}:${NACOS_PORT} 来连接到 Nacos 集群。

  • 服务注册

    curl -X PUT "http://${NACOS_HOST}:${NACOS_PORT}/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080"
  • 服务发现

    curl -X GET "http://${NACOS_HOST}:${NACOS_PORT}/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName"
  • 发布配置

    curl -X POST "http://${NACOS_HOST}:${NACOS_PORT}/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld"
  • 获取配置

    curl -X GET "http://${NACOS_HOST}:${NACOS_PORT}/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

高级特性

  • 一键安装而来的 Nacos 集群中包含 3 个实例,并且通过初始化插件自动完成自组集群并选举的操作。

nacos-4

  • 默认集成了 Mysql 作为数据源。在 Nacos-server-2.0.4 组件的环境配置中配置如下环境变量,可以切换到其他外部数据源。
名称必要描述
MYSQL_SERVICE_HOSTY数据库地址
MYSQL_SERVICE_PORTY数据库端口
MYSQL_SERVICE_USERY数据库用户名
MYSQL_SERVICE_PASSWORDY数据库密码
MYSQL_SERVICE_DB_NAMEY数据库名
  • 默认生成了 Nacos-server-2.0.4 的数据持久化目录。

nacos-5

  • 默认配置了 Nacos-server-2.0.4 的健康检查机制,保障实例故障时自动下线,恢复后自动上线。

nacos-6

· 阅读需 9 分钟

关于 Apache APISIX

Apache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅拥有众多实用的插件,而且支持插件动态变更和热插拔。

关于 Nacos

Nacos 是阿里巴巴开源的一个易于使用的动态服务发现、配置和服务管理平台。它提供了一组简单易用的特性集,可以帮助您快速实现动态服务发现,服务配置,服务元数据及流量管理,让您更敏捷和容易地构建,交付和管理微服务平台。Nacos 是构建以“服务”为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施。

注册中心

什么是注册中心

服务注册中心是服务要实现服务化管理的核心组件,类似于目录服务的作用,也是微服务架构中最基础的设施之一,主要用来存储服务信息,譬如服务提供者 URL 、路由信息等。注册中心的实现是通过一种映射的方式,将复杂的服务端信息映射为简单易懂的信息提供给客户端。

注册中心的核心功能为以下三点:

  1. 服务注册:服务提供方注册中心进行注册。
  2. 服务发现:服务消费方可以通过注册中心寻找到服务提供方的调用路由信息。
  3. 健康检测:确保注册到注册中心的服务节点是可以被正常调用的,避免无效节点导致的调用资源浪费等问题。

为什么需要注册中心?

注册中心本质上是为了解耦服务提供者和服务消费者,在微服务体系中,各个业务服务之间会频繁互相调用,并且需要对各个服务的 IP、port 等路由信息进行统一的管理。但是要如何进行管理呢?我们可以通过注册中心的 服务注册 功能将已有服务的相关信息提供到统一的注册中心进行管理。

通过上述描述,您可以了解到注册中心可以帮助用户通过映射快速找到服务和服务地址。随着业务更新迭代,服务会频繁发生变化,在服务端中注册了新的服务或者服务宕机后,客户端仍然可以通过注册中心的 服务发现 功能拉取服务列表,如果注册中心的服务节点发生变更,注册中心会发送请求通知客户端重新拉取。

如果服务端的服务突然宕机,并且没有向注册中心反馈,客户端可以通过注册中心的健康检查功能,进行固定时间间隔的主动上报心跳方式向服务端表明自己的服务状态。如果服务状态异常,则会通知注册中心,注册中心可以及时把已经宕机的服务节点进行剔除,避免资源的浪费。

Apache APISIX + Nacos 为用户提供了什么应用场景?

Apache APISIX + Nacos 可以将各个微服务节点中与业务无关的各项控制,集中在 Apache APISIX 中进行统一管理,即通过Apache APISIX 实现接口服务的代理和路由转发的能力。各个微服务在 Nacos 上注册后,Apache APISIX 可以通过 Nacos 的服务发现功能获取服务列表,查找对应的服务地址从而实现动态代理。

img

Apache APISIX 基于 Nacos 实现服务发现

前提条件

本文操作基于以下环境进行。

步骤一:服务注册

  1. 使用 Node.js 的 Koa 框架在 3005 端口启动一个简单的测试服务作为上游(Upstream)
const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
ctx.body = 'Hello World';
});

app.listen(3005);
  1. 在命令行中通过请求 Nacos Open API 的方式进行服务注册。
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=APISIX-NACOS&ip=127.0.0.1&port=3005&ephemeral=false'
  1. 执行服务注册后使用以下命令查询当前服务情况。
curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=APISIX-NACOS'

正确返回结果示例如下:

{
"name": "DEFAULT_GROUP@@APISIX-NACOS",
"groupName": "DEFAULT_GROUP",
"clusters": "",
"cacheMillis": 10000,
"hosts": [
{
"instanceId": "127.0.0.1#3005#DEFAULT#DEFAULT_GROUP@@APISIX-NACOS",
"ip": "127.0.0.1",
"port": 3005,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@APISIX-NACOS",
"metadata": {},
"instanceHeartBeatInterval": 5000,
"instanceHeartBeatTimeOut": 15000,
"ipDeleteTimeout": 30000,
"instanceIdGenerator": "simple"
}
],
"lastRefTime": 1643191399694,
"checksum": "",
"allIPs": false,
"reachProtectionThreshold": false,
"valid": true
}

步骤二:新增 Nacos 路由

使用 Apache APISIX 提供的 Admin API 创建一个新的路由(Route),APISIX 通过 upstream.discovery_type 字段选择使用的服务发现类型,upstream.service_name 需要与注册中心的对应服务名进行关联,因此创建路由时指定服务发现类型为 nacos

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"uri": "/nacos/*",
"upstream": {
"service_name": "APISIX-NACOS",
"type": "roundrobin",
"discovery_type": "nacos"
}
}'

在上述命令中,请求头 X-API-KEY 是 Admin API 的访问 token,可以在 conf/config.yaml 文件中的 apisix.admin_key.key 查看。

添加成功后,正确返回结果示例如下:

{
"action": "set",
"node": {
"key": "\/apisix\/routes\/1",
"value": {
"update_time": 1643191044,
"create_time": 1643176603,
"priority": 0,
"uri": "\/nacos\/*",
"upstream": {
"hash_on": "vars",
"discovery_type": "nacos",
"scheme": "http",
"pass_host": "pass",
"type": "roundrobin",
"service_name": "APISIX-NACOS"
},
"id": "1",
"status": 1
}
}
}

除此之外,您还可以在 upstream.discovery_args 中传递其他服务相关参数用于指定服务所在的命名空间或组别,具体内容可参考下表:

名字类型可选项默认值有效值说明
namespace_idstring可选public服务所在的命名空间
group_namestring可选DEFAULT_GROUP服务所在的组

步骤三:验证配置结果

使用以下命令发送请求至需要配置的路由。

curl -i http://127.0.0.1:9080/nacos/

正常返回结果示例如下:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 11
Connection: keep-alive
Date: Thu, 27 Jan 2022 00:48:26 GMT
Server: APISIX/2.12.0

Hello World

通过示例看到,Apache APISIX 中新增的路由已经可以通过 Nacos 服务发现找到正确的服务地址,并正常响应。

总结

本文为大家介绍了注册中心的概念以及 Apache APISIX 如何配合 Nacos 实现基于服务发现的路由代理。实际场景中如何进行 Apache APISIX 与 Nacos 的配合使用,您需要看具体的业务需求和过往技术架构。关于 nacos 插件的更多说明和完整配置信息,可参考官网文档:nacos

· 阅读需 12 分钟
双十一开启,Nacos Star 也突破 20000,从此迈上了一个新的里程碑。感谢大家的一路支持、信任和帮助!!!

image1.png

Nacos是Nacos团队三位一体战略的重要一环,它是一个更易于构建云原生生态的动态服务发现、配置管理和服务管理平台,它起源于阿里巴巴内部经过十年双十一洪峰考验的VIPServer/Configserver/Diamond三款产品,沉淀了简单易用、稳定可靠、性能卓越的核心竞争力,为广大开源用户提供了经过经过充分生产验证过的服务注册与配置中心产品。 截止目前,Nacos已发布40个迭代版本,无缝支持Dubbo/Spring-Cloud/服务网格生态。吸引了200多位优秀贡献者,积累了虎牙、好未来、小米等多家企业案例,官网累计获取44w+用户浏览;借此机会,我们代表 Nacos 社区一起回顾开源三年以来的发展历程和未来的发展方向。

image2.png

1. 项目演进

自从Nacos1.X版本突破10000 Star后,随着用户深入和大规模使用开始逐渐暴露Nacos1.X的性能问题,借此Nacos开启了2.0的发展阶段,全面升级了通信协议、服务一致性模型、支持服务网格生态和多语言生态,下面我们分别进行介绍。

1.1 长连接

Nacos1.x版本主要基于HTTP短连接构建服务注册与发现、配置管理系统。随着用户的服务量级的增大,HTTP短连接架构暴露了一些问题。为了克服短连接的固有的技术瓶颈,Nacos社区针对HTTP短连接架构进行了一次基于长连接的重构升级。

image3.png

在Nacos 1.X架构中,配置中心的推送功能通过长轮询构建,周期性地由客户端主动发送HTTP请求并在发生更新时返回变更内容;而服务注册中心的推送则通过UDP推送+HTTP定期对账来实现。然而,配置中心的长轮训、服务注册中心的定期对账,都需要周期性地对于服务端进行一次主动建连和配置传送,增大服务端的内存开销;随着Nacos用户的服务数和配置数规模的增大,服务端的内存泄漏风险也大大增加。 为了更好的支撑用户的性能要求,克服HTTP短连接架构固有的性能瓶颈,Nacos社区在阿里巴巴集团内部充分验证的基础上,进行了一次基于长连接的重构升级。长连接时代的Nacos2.x在原本1.x的架构基础上新增了对gRPC长连接模型的支持,同时保留对旧客户端和OpenAPI的兼容。

image4.png

通信层目前通过gRPC实现了长连接RPC调用和推送能力。升级完成之后,服务变化、配置变更等信息会通过gRPC的双向流主动推送给客户端,而客户端只需要针对各个长连接主动发送轻量级的心跳即可。升级后的技术架构极大地减少了服务端处理数据的开销;同时,由于长连接基于可复用TCP的机制,也大大降低了网络堵塞的风险。

压测验证:升级长连接之后,我们对Nacos2.0进行了大量压测。压测结果显示,Nacos2.0能够在10W级规模下,稳定运行;相比Nacos1.X版本的1.2W规模,提升约10倍。

image5.png

1.2 MCP及XDS协议支持

通过对于MCP协议及XDS协议的支持,目前服务网格生态领域已完全兼容Nacos,为Istio接入Nacos注册中心提供零侵入、高性能的微服务以及网关解决方案,帮助用户在使用非K8S服务发现的情况下,仍然可以无缝享用服务网格的无侵入式的服务治理策略。

image6.png

1.3 插件化支持

在插件化支持方面,Nacos社区通过为鉴权、配置加解密、多数据源等模块进行了插件化改造,支持用户进行灵活的插件实现和改造。用户可以根据自己的业务需要,通过实现相应的SPI接口和jar包的引入,方便地进行自定义的鉴权、加解密、多数据源等附加功能的实现。 插件化升级之后,Nacos充分实现了多种附加功能与核心功能的解耦合,可扩展性大大加强。

image7.png

1.4 多语言支持

随着Nacos2.0对于长连接的支持,多语言客户端也迈出了一大步。 当前Golang、Java、Python、C#等主流语言已完全拥抱Nacos2.0,支持通过gRPC协议进行高性能服务注册与发现、配置管理;另外,C++、Node.js、PHP的2.0客户端仍在快速迭代开发、生产验证过程中,同时希望更多社区朋友参与进来,共同构建更加完善的Nacos多语言生态。

2. 生态构建

开源3年以来,Nacos社区沿着三位一体战略规划进行生态演进和构建,通过开源、自研、商业化相互融合提供Nacos产品的优异可扩展性。

自研:利用阿里巴巴集团内部超高并发的场景,对Nacos开源产品进行性能和高可用的充分验证;具有更高的性能和超强的稳定性。

image8.png

公有云:Nacos充分在2.X系列版本中充分拥抱了云原生时代核心生态。Nacos团队内部利用公有云技术支持阿里巴巴集团和成千上万家公司大规模上云,为Nacos开源以及公有云Nacos产品提供了宝贵的生产实践经验,Nacos用户可以充分享受公有云弹性红利、安全、高可用能力。

开源:开源Nacos进行了大量的云原生生态演进。当前Nacos社区开源生态已相对完善:(1)无缝整合Dubbo、Nacos、Spring-cloud-alibaba/Seata/Sentinel阿里微服务DNS框架,并成为国内首选;(2)无缝整合服务网格生态,让用户平滑进入服务网格时代。(3)支持Dapr为用户多语言多一种选择,也为微服务多语言生态多一种探索方向,欢迎感兴趣小伙伴一起推动。

image9.png

3. 未来展望

3.1 进一步云原生化

随着云原生时代的到来,Nacos正在开展进行全面云原生化的探索。Nacos已支持了MCP协议及XDS协议,进行了初步的生产环境实践,为用户未来平滑迁移云原生服务框架做好了准备。 未来,我们将通过开展以下工作来提供云原生支持: 1、提供轻量级的Nacos Sidecar,为用户提供零侵入、轻量级的服务注册与发现能力; 2、支持通过Dapr进行sidecar构建,支持用户通过业务Pod+Dapr的方式构建微服务系统; 3、提供ServiceMesh化支持,将Nacos发展成云原生时代高性能注册中心,接入K8S核心生态。

3.2 更加完善的插件化体系

后期Nacos社区将会提供更加灵活的插件化体系,主要思路包括: 1、支持用户根据自己的业务场景,进行自定义的限流、熔断、容灾、多数据源等插件的开发和接入; 2、支持将配置中心和服务注册中心解耦,用户可以根据自己的需要将两者自由接入或删除。

3.3 更活跃的生态

Nacos社区将和Spring Cloud、Dubbo、Envoy、Dapr等社区一起推动微服务架构演进和标准化。

image10.png

4. 感谢贡献者

随着Nacos2.0的快速发展,Nacos社区产生了一些新晋的Committer:brotherlu-xcq、li-xiao-shuang、haoyann、horizonzy等,这些同学在长连接实现、配置加解密模块实现、多数据源支持、插件化等核心方面作出了大量的贡献。

image11.png

另外,Nacos社区参与了由中国科学院软件研究所和openEuler社区托管的开源之夏2021,由Wuyunfan-BUPT、li-xiao-shuang、Holdonbei、newJimmyChu及chenhongjing 5位同学分别完成了鉴权插件、配置加解密插件等5个课题,并取得了不错的进展,相信很快就可以和大家见面。

image11.png

除了这些已经成为Committer和参加了官方活动的贡献者,Nacos 还收获了其他大量作出优秀帮助的贡献者,目前已有200+ Contributors,非常感谢你们的付出!我们一起让Nacos更强大!!!

image12.png

最后欢迎加入社区贡献者队伍,共同进行Nacos云原生化实践!

image13.png

· 阅读需 7 分钟

Nacos 2.0.3

Nacos2.0.3 中,Nacos社区继续针对1.X到2.0.X升级的健壮性和高可用做了充分优化,扫除上生产的稳定性忧虑;Java/Spring-boot/Golang/C#/Cpp多语言客户端也全面支持Nacos2.0,拉齐多语言代差;并且优化了大量控制台UI的易用功能,提升用户使用效率。

主要变更内容如下:

## Features

[#6384] Add redo feature for nacos client naming.

## Enhancement

[#1469] Add cluster delete button.
[#5884] Add the permission for history config.
[#5909] Enhance LADP auth log print out when auth check failed.
[#5999] Adpat nacos endpoint in AddressServerMemberLookup.
[#6100] Enhance config managerment UI.
[#6129] Add ServerConfigChangeEvent when config file changed.
[#6142] Redo register and subscribe when reconnection auth check failed.
[#6160] Optimization of IP address acquisition method in nacos client.
[#6175] If the client already disconnect, ignore this request to avoid NPE.
[#6178] Unified configuration page style
[#6204] Get data from database if user or role info not found in cache.
[#6367] Add IOReactorExceptionHandler to avoid IOReactor out of loop when meet unknown Network error.
[#6386] Stop v1 distro verification when cluster upgraded to v2.
[#6403] Make the expired time of naming client be configurable in nacos-server.

## BugFix

[#6107] Fix Chinese account show with gibber in home page.
[#6109] Fix get InstanceUpgradeHelper instance error for double write service.
[#6116] Fix unable to check client beats when register same ip and port in old clients with high concurrent.
[#6169] Fix cluster page internationalization.
[#6198] Fix NPE when use StringUtils.join illegal.
[#6295] Fix instance metadata will not be removed for ip port client.
[#6335] Fix startup error when the JAVA_HOME path contains spaces under Linux/Unix/Mac system.
[#6382][#6476] Fix nacos-istio serviceInfo.getChecksum() always is empty.
[#6423] Fix yaml parse concurrent problem.

完整的Release Note请查看 2.0.3

从Nacos1.X升级Nacos2.0.X

Nacos服务端支持从1.X平滑升级到Nacos2.0.X;由于Nacos2.0对服务发现的数据结构进行了重构,因此升级过程中会采用异步双写数据的功能,在升级到2.0模式前,对数据进行校验,保证升级过程中的稳定运行。

在集群所有节点都升级到Nacos2.0.X版本之后,集群中的每一台节点都将开启自检,检查Nacos1.X模式下的数据是否和Nacos2.0模式下的数据一致,主要对比的是两个模式下的服务数及实例数是否相等,以及是否还有双写任务。 只有服务数及实例数相等,且没有双写任务之后,Nacos节点才会判定自身节点已经准备好升级到2.0模式,可以通过控制台的集群管理中节点元数据的readyToUpgrade字段来判断该节点是否准备完成。

当集群中所有节点都完成准备后,集群节点将会切换运行模式到2.0模式,此时请求流量将会切换至2.0模式运行,且开始接受gRPC的请求。如果未切换时,来自gRPC的请求将会提示Nacos cluster is running with 1.X mode, can't accept gRPC request temporarily. Please check the server status or close Double write to force open 2.0 mode.

另外,从Nacos2.0.2版本开始,Nacos为升级添加了一些接口方便用户检查升级状态,找到升级到2.0模式不成功的原因,并且在特殊情况下能够进行主动补偿。

比如接口/nacos/v1/ns/upgrade/ops/metrics, 可以快速的查看到当前节点的状态,如当前1.X模式的服务数,实例数;2.0模式的服务数,实例数;双写任务遗留量;对应模式缺失的服务名等等内容,帮助用户快速定位升级问题。

更多升级相关信息请查看 Nacos 2.0 升级文档

客户端支持2.0

目前Golang、C#、Cpp、nacos-spring-boot,客户端已经支持了nacos2.0的grpc能力,欢迎大家试用 ​

Python的多语言客户端正在紧张开发中,相信很快能与大家见面。 Nodejs部分欢迎社区小伙伴一起参与建设~

2.1版本预告

自2.0版本12月初社区发布后,经过数个版本的优化,功能和性能趋于稳定;因此社区开始规划2.1版本。

在Nacos2.1版本中,我们计划移除对Nacos1.X服务端的升级支持,以移除1.X模式及双写等冗余代码,提升代码质量及可读性,用户仍可以从2.0.X版本进行升级。

在功能上,Nacos2.1版本将会开放部分功能的插件化能力,如已经在进行的Selector插件,鉴权插件及配置加解密插件。

另外,我们会对Nacos2.0的第三方依赖进行一些精简,减少用户使用过程中依赖冲突的问题。

社区

感谢来自社区同学们的持续贡献,正是有了大家的共同努力,Nacos才能变得越来越完善。

在此郑重感谢对本次Release有卓越贡献的社区同学(根据字母顺序):

期待各位成为Nacos committer。

About Nacos

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

· 阅读需 8 分钟

Nacos2.0通过升级通信协议和框架、数据模型的方式将性能提升了约10倍,解决继 Nacos 1.0 发布逐步暴露的性能问题。本文通过压测 Nacos1.0,Nacos1.0升级Nacos2.0过程中,Nacos2.0 进行全面性能对比,直观的展示Nacos2.0所带来的性能提升。

压测准备

环境准备

为了方便Nacos部署升级和展示核心性能指标,我们是从阿里云微服务引擎MSE中购买的一个2核CPU+4G内存的三节点Nacos集群。

压测模型

为了展示不同规模下的系统表现,我们采用逐步增压的方式进行压测,将压力分为3个批次进行逐步启动,并观察每个批次下集群的运行表现。同时会在压力集群之外,再增加一个Dubbo服务的Demo,并使用Jmeter以100TPS的压力不停的调用,以模拟不同压力下,对实际业务调用存在的可能影响。

压测过程中,会在适当的时候对服务端和客户端进行升级;服务端的升级将直接使用MSE提供的一键升级功能,客户端的升级会使用分批次轮流重启的方式进行。

压测模型

压测过程

Nacos1.X Server + Nacos1.X Client

首先启动第一批施压集群,对MSE Nacos1.2.1进行施压,在6000个Providers的压力下,集群稳定时CPU大约25%,能够稳定保持6000实例。

1.X6000实例CPU 1.X6000实例

随后启动第二批施压集群,增加4000个Provider,合集10000个Provider。此时集群峰值CPU已经达到60%,稳定运行时大约在45%左右,集群能够稳定运行。

1.X10000实例CPU 1.X10000实例

在前两批的压力下,集群没有出现稳定性问题,所以Dubbo的调用保持正常,没有错误发生。

1.X10000实例Dubbo

当第三批施压集群启动之后,压力总计14000个Provider。此时集群先是短暂的注册到13000个实例,之后很快出现实例数下跌,CPU跑满的问题。并且缩小时间范围可以看到,下跌后的实例仍然在小范围抖动。

1.X14000实例CPU 1.X14000实例 1.X14000实例抖动

同时Dubbo的调用出现错误,从Consumer的日志可以看出,是由于服务端无法支撑这个级别的压力,导致Dubbo Provider被摘除,所以调用的时候出现了No provider的错误。

1.X14000实例Dubbo 1.X14000实例Dubbo错误

Nacos2.X Server + Nacos1.X Client

由于服务端升级期间,会进行实例的双写操作,因此在升级过程中服务端存储的实例数会是实际实例值的两倍。根据上述测试结果,需要先将实例数回滚回第一批6000实例之后,或是升级配置扩容机器之后再尝试升级。本文使用回滚压力的方式,先停止后启动的施压集群。让集群恢复正常后再执行升级。

升级前6000实例CPU 升级前6000实例 升级前6000实例Dubbo

从监控图中可以看出,在停止后两批压力后,集群很快就恢复到了正常,运行稳定,Dubbo调用也恢复正常。之后使用MSE的升级功能,进行升级。升级过程中由于双写的性能损耗,导致CPU有较大的抖动;而且因为双写导致的实例数翻倍,实际上相当于12000实例的极限压力,服务端仍然有一定的抖动,因此导致了些许Dubbo的错误。若是在非极限压力下升级,将不会有此影响。

升级后14000实例CPU 升级后14000实例 升级后14000实例Dubbo

随着服务端升级完成停止双写,消除了双写带来的性能损耗,CPU使用降低并趋于稳定,同时实例数也不再抖动,Dubbo调用完全恢复;如同1.X服务端一样,分两个批次启动施压集群,对比两个版本间在相同压力下的性能表现。

升级后14000实例CPU 升级后14000实例 升级后14000实例Dubbo

由于客户端依旧使用的是1.X的客户端,服务端的使用水位依然非常高,在全部压力启动后,CPU几乎达到100%;虽然没有像1.X服务端一样,出现大规模实例下跌,但是运行一段时间后依旧有少量的实例抖动,说明仅升级Nacos服务端到2.0版本能有一定的改善,但是没有彻底解决性能问题。

升级后14000实例抖动

Nacos2.X Server + Nacos2.X Client

为了完全释放Nacos2.0的性能,还需要将施压集群的客户端也升级到2.0以上版本。同样将分3个批次进行替换,期间由于Provider进行了重启,服务端有出现实例的下跌再恢复属于正常现象。随着施压集群的升级,可以发现CPU有了非常明显的下降,最终达到稳定时,CPU由最初的接近100%,降低到20%,集群稳定运行14000个实例。

2.X14000实例CPU 2.X14000实例 2.X14000实例Dubbo

压测结果

如上所述,我们能够得到2核CPU+4G内存的三节点集群在不同版本下的性能差异:

服务端版本客户端版本压力规模集群稳定性CPU使用
Nacos1.XNacos1.X14000完全不稳定100%
Nacos2.X(升级中)Nacos1.X6000有一定抖动100%
Nacos2.XNacos1.X14000有一定抖动100%
Nacos2.XNacos2.X14000稳定20%

由此可见,Nacos2.0确实对性能有较大的提升,新用户建议直接全部采用Nacos2.0,老用户建议先升级Server端,然后在逐步升级客户端释放红利。最后从整个压测视角的监控,来直观的感受一下不同版本在不同阶段的性能表现:

监控纵览

· 阅读需 6 分钟

随着Nacos2.0成熟稳定,Nacos-spring-boot发布0.1.10、0.2.10两个核心版本,全面支持了Nacos2.0,同时支持自动识别配置类型注入能力,修复了高并发场景下数据一致性问题。

<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.10</version>
</dependency>

Nacos-spring-boot老用户,将相关maven依赖进行如下替换,即可快速升级。

本文将系统介绍新版本增强能力,并且以一次生产环境的配置管理项目构建过程为例,详细描述新版本Nacos Spring Boot0.2.10版本的部署,帮助Spring Boot老用户快速上岸Nacos2.0,感受长连接带来的10倍性能提升。

Nacos-spring-boot新版本特性

新发布的0.1.10版本和0.2.10版本主要feature增强包括以下几个部分:

全面兼容Nacos2体系,向长连接时代演进

Nacos1体系中,配置中心的订阅、实时推送功能主要通过长轮训进行。尽管长轮训是HTTP短连接体系中被采用较多的动态刷新解决方案,但也不可避免地存在时延过高等缺陷;在生产实践中暴露了一定问题,如下面这两个链接所示

https://github.com/alibaba/nacos/issues/6345

https://github.com/alibaba/nacos/issues/2674

Nacos2体系将整个配置中心的订阅、推送功能重构成为了基于gRPC的长连接方案,保证了配置刷新实时推送;迄今为止,已经历了大量的生产环境考验。

自动识别配置的文件类型

在使用Nacos-spring-boot新版本之后,即使用户对配置类型未设置的情况下,nacos-spring-boot也会自动识别该配置的文件类型(json/yaml/properties)并给定默认值。

该机制极大降低了因为文件类型不匹配,业务侧出现配置处理错误的风险。下图为新版本Nacos-spring-boot项目在一次配置文件刷新过程中的工作机制。

springboot1.png

@NacosValue注解全面支持Spel表达式

Spel表达式全称为“Spring Expression Language”,是Spring自带的一种动态字符串构建方式表达式)。用户可以方便地使用Spel表达式来定义NacosValue,与Spring功能完美整合,减少SpringBoot用户们的工作量。

    @NacosValue(value = "${app.name}", autoRefreshed = true)
private String nacosNameAutoRefreshed;

@NacosValue(value = "${app.name:Nacos}", autoRefreshed = true)
private String nacosNameAutoRefreshedWithDefaultValue;

@NacosValue("${app.name}")
private String nacosNameNotAutoRefreshed;

@NacosValue("${app.nacosFieldIntValue:" + VALUE_1 + "}")
private int nacosFieldIntValue;

@NacosValue(value = "${app.nacosFieldIntValueAutoRefreshed}", autoRefreshed = true)
private int nacosFieldIntValueAutoRefreshed;

修复了高并发场景下的一致性问题

一些用户在使用Nacos-spring-boot项目进行大规模压测的过程中,出现了一些配置读取错误:在大流量频繁修改某些dataId的配置的过程中,客户端可能会拉取到旧版本的配置数据,导致客户端配置数据反复。 Nacos-spring-boot新版本通过增加智能锁、升级Nacos-spring依赖等方式,对于潜在的线程安全风险进行了修复。

生产演示

在Nacos服务端,为了方便Nacos部署升级和尽可能保证配置信息的信息安全,我们是从阿里云微服务引擎MSE 中购买的一个2核CPU+4G内存的三节点Nacos集群。

springboot2

在Nacos客户端,在Springboot老用户可以通过下面方式升级到Nacos-spring-boot新版本。

在 Maven 项目的 pom.xml 文件中增加(或升级)以下依赖来获取 Starter

<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.10</version>
</dependency>

注: 使用时请根据自定义构建的Spring Boot版本选择相应的nacos-config-spring-boot-starter版本:nacos-config-spring-boot-starter 版本 0.2.10 对应 Spring Boot 2.x 版本,版本 0.1.10 对应 Spring Boot 1.x 版本。

在 application.properties 文件中配置连接信息

nacos.config.server-addr=${nacos_server_address}:8848 注:${nacos_server_address}为占位符,表示Nacos server的地址,可直接填入上文中购买的Nacos集群的公网或内网地址。

使用 @NacosPropertySource 加载 dataId 为 example 的配置源,并开启自动更新

@SpringBootApplication
@NacosPropertySource(dataId = "com.alibaba.nacos.example.properties", autoRefreshed = true)
public class NacosConfigApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication.class, args);
}
}

使用 @NacosValue 注解设置属性值。

@Controller 
@RequestMapping("config")
public class ConfigController {
@NacosValue(value = "${connectTimeoutInMills:5000}", autoRefreshed = true)
private int connectTimeoutInMills;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public int get() {
return connectTimeoutInMills;
}
}

结果验证

在本地启动客户端项目,并运行以下命令:

curl localhost:8080/config/get

若返回以下信息,则说明 SDK 可正常使用。

3000

在MSE控制台将示例配置 com.alibaba.nacos.example.properties 更改为以下内容并发布。

connectTimeoutInMills=6000

若Console打印出更新的配置内容 ,则说明SDK的配置自动更新功能正常;工程正式跨入高性能配置中心时代。