掌门教育微服务体系Solar第3弹:Nacos企业级落地下篇

本文涉及的产品
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
云原生网关 MSE Higress,422元/月
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: 在高速发展的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做运营与服务,必须提高每个人效,这就需要技术驱动。因此掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。-- 张翼(掌门教育创始人兼CEO)

1.png

联席作者:谢璐 谢庆芳 伊安娜 任浩军
郑重鸣谢:Nacos - 彦林,Spring Cloud Alibaba - 小马哥、洛夜,Nacos 社区 - 张龙(pader)、春少(chuntaojun)

相关文章推荐:

前言

在高速发展的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做运营与服务,必须提高每个人效,这就需要技术驱动。因此掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。

-- 张翼(掌门教育创始人兼CEO)

掌门教育自2014年正式转型在线教育以来,秉承“让教育共享智能,让学习高效快乐”的宗旨和愿景,经历云计算、大数据、人工智能、 AR / VR / MR 以及现今最火的 5G ,一直坚持用科技赋能教育。掌门教育的业务近几年得到了快速发展,特别是今年的疫情,使在线教育成为了新的风口,也给掌门教育新的机遇。

随着业务规模进一步扩大,流量进一步暴增,微服务数目进一步增长,使老的微服务体系所采用的注册中心 Eureka 不堪重负,同时 Spring Cloud 体系已经演进到第二代,第一代的 Eureka 注册中心已经不大适合现在的业务逻辑和规模,同时它目前被 Spring Cloud 官方置于维护模式,将不再向前发展。如何选择一个更为优秀和适用的注册中心,这个课题就摆在了掌门人的面前。经过对 Alibaba NacosHashiCorp Consul等开源注册中心做了深入的调研和比较,最终选定 Alibaba Nacos 做微服务体系 Solar 中的新注册中心。

背景故事

基础架构部选择新的注册中心,测试组需要配合对业界成熟的注册中心产品做分析和比较。由于掌门教育采用的是比较纯净的 Spring Cloud 技术栈,所以我们需要围绕它的注册中心,从测试角度,进行功能和性能上研究。

Spring Cloud 技术栈官方支持 Netflix EurekaHashiCorp ConsulZookeeper 三个注册中心,它们可以相互间实现无缝迁移,Alibaba Nacos 是新加盟 Spring Cloud 技术栈的新成员。测试组的同学们对上述四个注册中心做了一一研究和分析,鉴于时间紧迫,除了 EurekaNacos 之外,其它两个中间件未做深入的功能测试和性能测试。下面提供来自阿里巴巴 Nacos 官方某次业界宣讲的资料截图以供大家参考:

  • Eureka 介绍

2.png

  • Zookeeper 介绍

3.png

  • Consul 介绍

4.png

  • 上述三个注册中心比较

5.png

本文将围绕 Alibaba Nacos 着重针对其功能测试和性能测试两方面进行剖析和介绍。

Nacos 测试篇

Nacos 性能测试

① Nacos Server 性能测试

开发部署了 UATNacos ,测试亲自压测。

  • 核心脚本
def registry(ip):
    fo = open("service_name.txt", "r")
    str = fo.read()
    service_name_list = str.split(";")
    service_name = service_name_list[random.randint(0,len(service_name_list) - 1)]
    fo.close()
    client = nacos.NacosClient(nacos_host, namespace='')
    print(client.add_naming_instance(service_name,ip,333,"default",1.0,{'preserved.ip.delete.timeout':86400000},True,True))
    while True:
      print(client.send_heartbeat(service_name,ip,333,"default",1.0,"{}"))
      time.sleep(5)
  • 压测数据

表格 1.jpg

  • 压测结果图

6.png

7.png

Nacos Server 是3台 1C4G 集群,同时承受1499个服务和12715个实例注册,而且 CPU 和内存长期保持在一个合适的范围内,果真 Nacos 性能是相当 OK 的。

Nacos 功能测试

① Nacos Server 接口测试

表格2.jpg

更多更详 API 请参见 Nacos 官方文档: Open API 指南

https://nacos.io/zh-cn/docs/open-api.html

② Nacos Eureka Sync 测试

  • 交叉注册

网关,服务 A ,服务 B 各10台实例,网关注册 EurekaA 注册 NacosB 注册 Eureka ,同步正常,可调用。

  • 压力测试

请求大于100万次,查看 Sync Server 会不会受到影响,结果 ErrorRequest = 0,同步服务数和实例数没有变化。

8.png

  • 有无损调用

网关 Sync Server 挂掉,网关服务 Eureka 同步 Nacos 失败,不影响网关 -> A -> B 调用。

  • 自动创建同步

发布系统第一次发布应用到 Eureka / Nacos ,会自动创建 Eureka -> Nacos 的同步任务或 Nacos -> Eureka 的同步任务

9.png

  • 减少 Sync Server

Sync Server 4C8G ,停止机器,逐台递减,结论:平均1台 4C8G 机器最大可同步100个服务。

  • 增加 Sync Server

2台 Etcd 节点,停机一台,Etcd 读取超时,结论:600个服务至少2台 Etcd 节点,这里重点强调,新增服务时, Hash 算法虚拟节点数,务必和原有的保持一致,不然会出现同步失败,影响跨注册中心调用。

10.png

  • 重启 Sync Server

增加 Sync Server 个数,重启 Sync Server ,各节点同步数重新计算且均衡。

③ Nacos Client 功能测试

Nacos Client 界面重点测试集群管理,服务列表和权限控制。

  • Nacos Server 重启后,集群管理界面正常展示3台集群节点 IP
  • 服务注册 Nacos Server 后,服务列表新增注册上去的服务名和实例个数,而且可查看详情。

11.png

  • 服务上下线操作,健康状态和元数据等展示正常。
  • 编辑,删除等操作只有具备 Admin 权限的人员才可操作。

④ Nacos Client 自动化测试

  • 自动化测试链路

全链路测试路径

API网关 -> 服务A(两个实例) -> 服务B(两个实例)

12.png

全链路服务部署

表格3.jpg

  • 自动化测试入口

结合 Spring Boot JunitTestApplication.class 为测试框架内置应用启动程序, MyTestConfiguration 用于初始化所有测试用例类。在测试方法上面加入 JUnit@Test注解

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TestApplication.class, MyTestConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyTest {
    @Autowired
    private MyTestCases myTestCases;

    private static long startTime;

    @BeforeClass
    public static void beforeTest() {
        startTime = System.currentTimeMillis();
    }

    @AfterClass
    public static void afterTest() {
        LOG.info("* Finished automation test in {} seconds", (System.currentTimeMillis() - startTime) / 1000);
    }

    @Test
    public void testNoGray() throws Exception {
        myTestCases.testNoGray(gatewayTestUrl);
        myTestCases.testNoGray(zuulTestUrl);
    }

    @Test
    public void testVersionStrategyGray() throws Exception {
        myTestCases.testVersionStrategyGray1(gatewayGroup, gatewayServiceId, gatewayTestUrl);
        myTestCases.testVersionStrategyGray1(zuulGroup, zuulServiceId, zuulTestUrl);
    }
}
@Configuration
public class MyTestConfiguration {
    @Bean
    public MyTestCases myTestCases() {
        return new MyTestCases();
    }
}
  • 基于 Nacos Client 的普通调用自动化测试

在测试方法上面增加注解 @DTest ,通过断言 Assert 来判断测试结果。注解 @DTest 内容如下:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DTest {

}

代码如下:

public class MyTestCases {
    @Autowired
    private TestRestTemplate testRestTemplate;

    @DTest
    public void testNoGray(String testUrl) {
        int noRepeatCount = 0;
        List<String> resultList = new ArrayList<String>();
        for (int i = 0; i < 4; i++) {
            String result = testRestTemplate.getForEntity(testUrl, String.class).getBody();

            LOG.info("Result{} : {}", i + 1, result);

            if (!resultList.contains(result)) {
                noRepeatCount++;
            }
            resultList.add(result);
        }

        Assert.assertEquals(noRepeatCount, 4);
    }
}
  • 基于 Nacos Client 的灰度蓝绿调用自动化测试

在测试方法上面增加注解 @DTestConfig ,通过断言 Assert 来判断测试结果。注解 DTestConfig 注解内容如下:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DTestConfig {
    // 组名
    String group();

    // 服务名
    String serviceId();

    // 组名-服务名组合键值的前缀
    String prefix() default StringUtils.EMPTY;

    // 组名-服务名组合键值的后缀
    String suffix() default StringUtils.EMPTY;

    // 执行配置的文件路径。测试用例运行前,会把该文件里的内容推送到远程配置中心或者服务
    String executePath();

    // 重置配置的文件路径。测试用例运行后,会把该文件里的内容推送到远程配置中心或者服务。该文件内容是最初的默认配置
    // 如果该注解属性为空,则直接删除从配置中心删除组名-服务名组合键值
    String resetPath() default StringUtils.EMPTY;
}

代码如下:

public class MyTestCases {
    @Autowired
    private TestRestTemplate testRestTemplate;

    @DTestConfig(group = "#group", serviceId = "#serviceId", executePath = "gray-strategy-version.xml", resetPath = "gray-default.xml")
    public void testVersionStrategyGray(String group, String serviceId, String testUrl) {
        for (int i = 0; i < 4; i++) {
            String result = testRestTemplate.getForEntity(testUrl, String.class).getBody();

            LOG.info("Result{} : {}", i + 1, result);

            int index = result.indexOf("[V=1.0]");
            int lastIndex = result.lastIndexOf("[V=1.0]");

            Assert.assertNotEquals(index, -1);
            Assert.assertNotEquals(lastIndex, -1);
            Assert.assertNotEquals(index, lastIndex);
        }
    }
}

初始默认无灰度蓝绿的配置文件 gray-default.xml

<?xml version="1.0" encoding="UTF-8"?>
<rule>

</rule>

灰度蓝绿生效的配置文件 gray-strategy-version.xml

<?xml version="1.0" encoding="UTF-8"?>
<rule>
    <strategy>
        <version>1.0</version>
    </strategy>
</rule>
  • 基于 Nacos Client 的自动化测试报告样例
---------- Run automation testcase :: testStrategyCustomizationGray() ----------
Header : [a:"1", b:"2"]
Result1 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
Result2 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
Result3 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
Result4 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
* Passed
---------- Run automation testcase :: testVersionRuleGray() ----------
Result1 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
Result2 : zuul -> solar-service-a[192.168.0.107:3001][V=1.0][R=dev][G=solar-group] -> solar-service-b[192.168.0.107:4001][V=1.0][R=qa][G=solar-group]
Result3 : zuul -> solar-service-a[192.168.0.107:3002][V=1.1][R=qa][G=solar-group] -> solar-service-b[192.168.0.107:4002][V=1.1][R=dev][G=solar-group]
Result4 : zuul -> solar-service-a[192.168.0.107:3001][V=1.0][R=dev][G=solar-group] -> solar-service-b[192.168.0.107:4001][V=1.0][R=qa][G=solar-group]
* Passed

Nacos 测试总结

Nacos 不仅性能好,而且界面简洁,这样的注册中心你值得拥有。

作者介绍

  • 吴毅挺,掌门技术副总裁,负责技术中台和少儿技术团队。曾就职于百度、eBay 、携程,曾任携程高级研发总监,负责从零打造携程私有云、容器云、桌面云和 PaaS 平台。
  • 任浩军,掌门基础架构部负责人。曾就职于平安银行、万达、惠普,曾负责平安银行平台架构部 PaaS 平台 Halo 基础服务框架研发。10 多年开源经历,Github ID:@HaojunRen,Nepxion 开源社区创始人,Nacos Group Member,Spring Cloud Alibaba & Nacos & Sentinel & OpenTracing Committer。

参与 Nacos 落地的基础架构部成员,包括:

  • 童子龙,张彬彬,廖梦鸽,张金星,胡振建,谢璐,谢庆芳,伊安娜

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

相关文章
|
5月前
|
人工智能 安全 Nacos
Nacos 3.0:微服务与AI融合的技术新纪元
Nacos 3.0:微服务与AI融合的技术新纪元
312 83
|
5月前
|
人工智能 安全 Java
Nacos 3.0:从微服务治理到AI服务治理的跃迁
Nacos 3.0:从微服务治理到AI服务治理的跃迁
331 5
|
5月前
|
人工智能 自然语言处理 安全
Nacos 3.0:微服务与AI融合的新一代动态治理平台
Nacos 3.0:微服务与AI融合的新一代动态治理平台
318 2
|
3月前
|
人工智能 API Nacos
MCP Registry 官方发布:Nacos 原生支持,借助 HiMarket 构建企业级私有 MCP 市场
最近,MCP 社区发布了 MCP Registry(2025‑09‑08,预览版),为公开 MCP Server 提供“统一目录服务和开放 API”。Nacos 已原生支持 MCP Registry API,可直接作为“MCP Registry”对外提供标准 REST/OpenAPI 服务端,天然融入企业现有注册中心与配置治理体系,并与 Higress/HiMarket 对接打通,让企业能够高效的构建自己的私有 MCP 市场。
356 37
|
5月前
|
人工智能 自然语言处理 Nacos
Nacos 3.0:微服务与AI融合的全新治理平台
Nacos 3.0:微服务与AI融合的全新治理平台
254 46
|
12月前
|
存储 网络协议 Nacos
高效搭建Nacos:实现微服务的服务注册与配置中心
Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台。它旨在帮助开发者更轻松地构建、部署和管理分布式系统,特别是在微服务架构中。
1894 82
高效搭建Nacos:实现微服务的服务注册与配置中心
|
11月前
|
人工智能 安全 Java
微服务引擎 MSE:打造通用的企业级微服务架构
微服务引擎MSE致力于打造通用的企业级微服务架构,涵盖四大核心内容:微服务技术趋势与挑战、MSE应对方案、拥抱开源及最佳实践。MSE通过流量入口、内部流量管理、服务治理等模块,提供高可用、跨语言支持和性能优化。此外,MSE坚持开放,推动云原生与AI融合,助力企业实现无缝迁移和高效运维。
444 1
|
Java 网络安全 Nacos
Nacos作为流行的微服务注册与配置中心,其稳定性与易用性广受好评
Nacos作为流行的微服务注册与配置中心,其稳定性与易用性广受好评。然而,“客户端不发送心跳检测”是使用中常见的问题之一。本文详细探讨了该问题的原因及解决方法,包括检查客户端配置、网络连接、日志、版本兼容性、心跳检测策略、服务实例注册状态、重启应用及环境变量等步骤,旨在帮助开发者快速定位并解决问题,确保服务正常运行。
212 5