Spring Cloud+Nacos+KMS 动态配置最佳实践

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
简介: 本文讲述了 Spring Cloud 应用中结合 Nacos 实现了运行期配置动态更新的功能,以及在此基础上结合 KMS 在不改动代码的情况下对应用使用的敏感配置进行保护,解决将配置迁移到 Nacos 中可能存在的数据安全顾虑,并对其底层工作原理做了简单介绍。

作者: 柳遵飞


前言


Spring Cloud 框架在微服务领域被广大开发者所使用,@Value 是每位开发者都会接触到的注解,在 SpringBean 中可以通过 Value 注解引用 application.properties 属性,实现配置代码分离,提升应用代码部署的灵活性,但无法在运行期动态更新配置。Nacos 是一款集服务发现和配置管理功能的中间件产品,其中配置中心可以实现运行期配置实时生效,将工程本地的属性文件配置在 Nacos 中,在应用中做一些配置上的改动就可以轻易集成 Nacos 实现配置的动态刷新,工程依赖的属性多种多样,其中把有一些敏感数据配置在中心化的 Nacos 中可能会存在一些安全性层面的顾虑,Nacos 也有方法来应对这个问题,本次我们就对以上问题进行介绍。


本文将以如下步骤展开:


  • 集成 Nacos 实现动态配置更新
  • 集成 KMS 零代码改造实现敏感配置加密
  • Spring Cloud+Nacos 工作原理介绍


SpringCloud 应用配置常规用法


在一个 Spring Cloud 应用中,可以在 Bean 中通过 @Value 注解来引用 Spring 上下文中的属性值,可以引用环境变量,JVM 参数以及我们常见的 application.properties 配置文件中的属性。


以下是该种用法简易实例:


application.properties:


app.switch=true
app.threadhold=0.8


一个简单的 Spring Bean:


@Component
public class AppConfig{

  @Value("${app.switch:false}")
  boolean switch;

  @Value("${app.threadhold}")
  double threadhold;

}


AppConfig 可以被其他的 SpringBean 引用,可以正常获取到配置在 application.properties 中的 app.switch 和 app.threadhold 属性。


当我们需要修改 app.switch 和 app.threadhold 的值时,我们需要修改配置文件中的内容并对应用进行重启,当我们需要频繁修改某些业务参数时,重启应用的效率较低。


集成 Nacos 实现配置动态刷新


以下我们将介绍如何在 Spring Cloud 应用中结合 Nacos 实现配置动态更新。


Spring 在 2.4.x 版本开始,引入了 spring.config.import 参数,可以自定义外部的属性源,通过 Spring Cloud Alibaba 组件可以实现将 Nacos 中的配置添加为 Spring 的属性源之一,因此在一个 Spring Bean 中也可以通过 Value 注解读取到 Nacos 中的配置。


以下我们将 Spring Cloud Alibaba 简称为 SCA。


1. pom 中添加 SCA nacos config 依赖


<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
      <version>${spring.cloud.alibaba.version}</version>
</dependency>

组件的版本名称和 spring boot 版本相关,可以根据 sca 官网的版本说明选择对应的版本:https://sca.aliyun.com/docs/2021/overview/version-explain/


2. 初始化 Nacos 配置


可以选择开源 nacos 或者购买商业化 MSE Nacos 版本,以下的图示为商业化 Nacos。


假设我们的应用为支付业务的应用,应用名为 pay。


在 Nacos 实例中可以创建 dataId=pay-application.properties,group=core 的配置。

image.png

3. 修改应用工程中的 application.properties


spring.config.import=nacos:pay-application.properties?group=core&refreshEnabled=true
spring.cloud.nacos.config.server-addr={server addr}


添加 sping.config.import 参数将 Nacos 中 dataId=pay-application.properties,group=core 的配置添加为属性源,refreshEnabled=true 表示当 Nacos 中的配置变更时,需要同步刷新 Spring 中的属性源。


添加 spring.cloud.nacos.config.server-addr 参数指定连接的 Nacos 地址。


删除工程本地 application.properties 的 app.switch,app.threadhold 参数。


4. Spring Bean 中添加 RefreshScope 注解


@Component
@RefreshScope
public class AppConfig{

  @Value("${app.switch:false}")
  boolean switch;

  @Value("${app.threadhold}")
  double threadhold;

}


在业务代码中仍然使用 Value 注解来引用 Spring 上下文中的配置,但需要在 Bean 上添加 RefreshScope 注解,只有添加该注解,Spring 才会在内部属性源更新时将属性刷新到当前的 Bean 中。


重启应用后,此时我们在 Nacos 中对配置 pay-application.properties 中属性进行修改,应用程序中 AppConfig 的参数值就会动态更新。


集成 KMS 实现配置无感加密


上一节中我们通过集成 Nacos 实现了 SpringCloud 应用的配置动态更新,应用中的配置类型多种多样,其中某些配置具有较高的敏感性,比如数据库的连接地址,用户名密码,一些第三方组件的秘钥,Token 以及其他业务功能中敏感配置等等,这些配置的安全性非常重要,如果泄漏可能会对业务造成不可估量的影响。这些数据在 Nacos 中是存放在 pay-application.properties 中,以下是示例:

以下示例中的敏感参数均为模拟数据:


dataId=pay-application.properties,group=core:


# 数据库配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myapp
spring.datasource.username=user001
spring.datasource.password=pass!@#$%

# 秘钥Token等 secret and token
app.secret=GFYIdryujixxx
key.token=eedsjpp56hko8h

# 业务参数
app.switch=false
app.threadhold=0.8


SpringBean:


@Component
public class SecretConfig{

  @Value("${app.secret}")
  String secret;

  @Value("${app.token}")
  String token;

  @PostConstruct
  public void init(){
    //init client use token and secret
  }
}


@Component
public class AppConfig{

  @Value("${app.switch:false}")
  boolean switch;

  @Value("${app.threadhold}")
  double threadhold;

}


对于其中数据库密码,Token 等数据,通常会有更多安全性层面的考虑,比如这些敏感配置存储在 Nacos 中安全性是否可以保证,应用访问 Nacos 传输过程中数据是否存在泄漏可能性,敏感配置和普通的业务配置能否设置不同的读写权限,要实现以上安全性的要求,业务的代码是否可以尽量低成本改造等等。


要实现以上的安全性诉求,我们要做到以下几点:


1. 敏感配置在 Nacos 需要加密存储,不能直接明文存储

2. 敏感配置在传输过程中需要加密传输,防止中间网络设备通过抓包方式窃取数据。

3. 应用中的业务代码不能感知配置是否加密,仍需要按照之前的方式读取属性值,降低改造成本。


以下我们将介绍如何通过集成 KMS 实现零代码改造实现上述诉求。


加密配置拆分

如果我们期望将普通业务配置和敏感配置分离,我们可以 dataId=pay-application.properties,group=core 的配置进行拆分,将敏感数据单独拆分出一个独立的加密 Nacos 配置,比如 dataId=cipher-kms-aes-256-pay-application.properties,group=secret,用于存放数据源 token 等相关的敏感配置。为了防止解密配置和普通配置属性文件中的属性值重复,我们可以在加密配置中的属性值统一加上 encrypted 前缀。


Nacos 中的配置

1. dataId=cipher-kms-aes-256-pay-application.properties,group=secret


# 数据库配置
encrypted.spring.datasource.driver-class-name=com.mysql.jdbc.Driver
encrypted.spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
encrypted.spring.datasource.username=user001
encrypted.spring.datasource.password=pass!@#$%

# 秘钥Token等 secret and token
encrypted.app.secret=test_GFYIdryujixxx
encrypted.key.token=test_eedsjpp56hko8h


2. dataId=pay-application.properties,group=core


原先的 pay-application.properties 中的属性暂时保持不动,等应用程序侧的所有节点引入新配置 cipher-kms-aes-256-pay-application.properties 之后,再对其做变更。


工程内配置改造

1. 引入 MSE 插件扩展包


加密的配置在存储和网络传输过程中都是密文,因此需要在应用侧支持解密的功能,在 pom 中引入解密插件。


<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client-mse-extension</artifactId>
    <version>1.0.4</version>
</dependency>


2. 调整项目工程下的 application.properties


在 spring.config.import 添加新加配置 cipher-kms-aes-256-pay-application.properties,以及设置 KMS 初始化相关参数。


spring.config.import=nacos:cipher-kms-aes-256-pay-application.properties?group=secret&refreshEnabled=true,nacos:pay-application.properties?group=core&refreshEnabled=true
spring.cloud.nacos.config.server-addr={server addr}

# 设置客户端NacosClient访问KMS所需参数
spring.cloud.nacos.config.kms_region_id=cn-hangzhou
spring.cloud.nacos.config.kmsEndpoint=kst-xxx.cryptoservice.kms.aliyuncs.com
spring.cloud.nacos.config.kmsVersion=v3.0
spring.cloud.nacos.config.kmsClientKeyFilePath=clientKey_hangzhou.json
spring.cloud.nacos.config.kmsPasswordKey=10xxxd1d
spring_cloud_nacos_config_kmsPasswordKey=10xxxd1d
spring.cloud.nacos.config.kmsCaFilePath=clientKey_hangzhou.json

客户端 NacosClient 访问 KMS 所需参数和 KMS 版本相关,具体步骤及后续更新见 MSE 官方文档:https://help.aliyun.com/zh/mse/user-guide/create-and-use-encrypted-configurations


修改配置重启业务应用完成后,此时应用程序读取的还是 Nacos 中 pay-application.properties 的属性值,但是此时 encrypted. 前缀的相关属性已经存在于 Spring 的上下文中。


加密配置迁移

当前应用程序重启完成之后,我们对 Nacos 的配置做如下修改:


dataId=pay-applicaition.properties,core=core


# 数据库配置
spring.datasource.driver-class-name=${encrypted.spring.datasource.driver-class-name}
spring.datasource.url={encrypted.spring.datasource.url}
spring.datasource.username=${encrypted.spring.datasource.username}
spring.datasource.password=${encrypted.spring.datasource.password}

# 秘钥Token等 secret and token
app.secret=${encrypted.app.secret}
key.token=${encrypted.key.token}

# 业务参数
app.switch=false
app.threadhold=0.8


将原先在 pay-applicaition.properties 中的敏感属性以 ${} 方式引用 cipher-kms-aes-256-application.properties 中的属性 key。其中 cipher-kms-aes-256-pay-application.properties 中的属性并不会被应用程序代码中直接引用,而是在 pay-application.properties 通过配置嵌套的模式间接引用,程序代码中本质上还是读取的 pay-application.properties 中的属性。


过程中,我们只对工程中的配置文件做了改造,而业务代码层面没有做任何改动。改造完成后,cipher-kms-aes-256-pay-application.properties 配置中的内容在 Nacos 服务端,传输过程中以及应用本地的缓存中都是密文形式,在业务应用进程中,NacosClient 内部会和 KMS 交互完成密文解密成明文。


配置动态刷新工作原理介绍

通过以上改造,我们就完成了 Spring Cloud+Nacos 实现配置动态刷新的功能,下面我们将介绍 Spring Cloud + Nacos 实现动态配置刷新的工作原理。


启动加载机制

Spring Bean 的初始化需要读取 Nacos 中的配置,因此 Nacos 初始化的过程是在所有 Spring Bean 初始化之前进行。Spring Clound Aliababa 组件会根据当前的 application.properties 参数对 Nacos 进行初始化,从 Nacos Server 加载配置,并构建为 NacosPropertySource。在此阶段中,Spring 也可以从 JVM 或者环境变量中读取参数,因此 Nacos 初始化所需的参数也可以通过 JVM 参数和环境变量进行设置,比如 Nacos server 的地址,命名空间 namespace,鉴权相关的 accessKey 及 secretKey 等。

image.png

在构建好完整属性源之后,Spring 会进入 Bean 的初始化流程中,只有在该阶段正常完成了 Nacos 的初始化以及 Nacos 配置的加载,Bean 才可以正常读取到 Nacos 中的配置。


动态更新机制

在上一章节中,我们在设置 spring.config.import 参数时,指定了 refreshEnabled=true 参数,该参数表示是否需要动态监听远端 NacosServer 中该配置的变化,如果不指定该参数,SCA 只会在启动时加载一次配置,并不会在运行期监听配置变化以及更新 NacosPropertySource 中的内容,SpringBean 中的属性值也就无法运行期更新。

image.png

可以按照上图图示中的数字顺序了解 Nacos 配置动态更新的机制,当 spring.config.import 配置中添加了 refreshEnabled=true 参数,SCA 就会在 Spring 容器初始化完成后对 Nacos 配置进行监听,时间点上和配置启动加载的时间点并不一致,配置初始化的时间点是在所有 Bean 初始化之前,而监听配置变更的时间点是在所有 Bean 完成初始化之后。


成功监听后,当我们在 Nacos 控制台对配置进行更新时,应用程序中的 NacosClient 会通知 SCA 配置发生变化,SCA 在接受到底层 Nacos 回调后会向 Spring 发布 RefreshEvent 事件,Spring 中的 ContextRefresher 会接受该事件,将最新的配置更新到 NacosPropertySource 中,更新 Enviroment 对象,并且发布 RefreshScopeRefreshedEvent 事件,对所有添加了 RefreshScope 注解以及 ConfigurationProperties 注解的 SpringBean 进行重新初始化,从未获取到最新的属性值。


以上流程中 spring.config.import 配置中的 refreshEnabled=true 参数决定了 SCA 是否会监听配置并在 Nacos 中配置的变化时更新 Enviroment,而在 Bean 中添加 RefreshScope 注解以及 ConfigurationProperties 直接决定了当 Enviroment 对象中的属性发生变化时刷新 Bean 中的属性值。


属性源的优先级

上面我们了解到 Value 注解可以读取环境变量,JVM,application.properties 中的配置,不同的属性源中的属性 key 可能重复,这种情况下,Spring 读取属性有一个优先级,如下图所示,优先级为 JVM 参数>环境变量>Nacos 配置(spring.config.import 参数引入属性源)>工程本地 application.properties。

image.png

Nacos 中设置的属性值会覆盖工程本地的属性文件,但是其优先级低于 JVM 和环境变量,如果在环境变量和 JVM 参数配置了相同的参数,Nacos 中的配置将不会生效。SCA 在实现配置动态加载遵循了 Spring Boot 官方推荐的属性源优先级顺序,参考:https://docs.spring.io/spring-boot/reference/features/external-config.html


此外,spring.config.import 参数可以指定多个属性源,不同的属性源之间通过逗号 "," 分隔,多个不同属性源之间,引入顺序靠前,优先级更低。

image.png

在 spring boot 2.4 之前的版本中,Spring 不支持通过 spring.config.import 指定外部属性源,SCA 内部提供了 spring.cloud.nacos.config.shared-configs 和spring.cloud.nacos.config.extension-configs 参数来指定多个 Nacos 配置属性源,在最新的 SCA 版本 2023.0.1.3 中已经废弃这两个参数,统一到标准的 spring.config.import 参数。此外,在低版本的 Spring 中,支持在 bootstrap.yml 文件中配置参数,该种用法也在新版本 Spring 中废弃,统一将参数配置 application.properties,我们建议对依赖低版本的应用代码进行升级,统一改造为标准的方法进行配置。


Nacos日志

Nacos 扮演了配置动态推送的核心功能,通过查看 Nacos 的启动及运行时日志,可以帮助大家更好地理解两者整合的内部原理,并且有助于大家自主排查配置中心的常见问题,Nacos 客户端的日志目录默认在 {user.home}/logs/nacos/目录下,其中 {user.home} 是应用进程运行所属用户的主目录,在 Linux 系统中,如果进程以 root 启动,日志默认在/root/logs/nacos/下,如果以 admin 用户启动,日志默认在/home/admin/logs/nacos/下。在 nacos 目录下,我们可以看到 remote.log,config.log,naming.log 三个日志文件,其中 remote.log 记录 Nacos 客户端和服务端的长连接相关的日志,naming.log 是服务管理相关日志,config.log 是我们需要核心关注的配置相关日志,其中记录着 Nacos 客户端和 Nacos 服务端交互的详细日志。以下是几个关键的日志:


  • add-listener:表示应用程序监听了配置,包括 namespace,dataId,group 三元组,只有正常监听了配置,才能在配置变更时收到推送
  • server-push:表示应用程序收到了服务端的配置变更推送事件。
  • data-received:表示应用程序收到推送事件后向服务端查询到了配置内容,包括 namespace,dataId,group 三元组以及接受到的配置 md5,可以和 Nacos 控制台比对 md5 值来判断是否接受到正确的版本
  • notify-listener:表示应用程序收到了更新后的配置内容,并且尝试将最新的配置内容回调给对应的监听器,比如通知 SCA 重新加载 Nacos 的配置并且更新 Spring 上下文。
  • notify-ok:表示 Nacos 已经成功回调了监听器,监听器中的回调已经正常执行。
  • notify-error:表示 Nacos 回调了监听器,但是监听器执行是抛出了异常,从业务视角,该种情况会表现配置更新没有效果,需要根据具体异常进行处理。
  • notify-block-monitor:表示 Nacos 回调了监听器,但监听器执行超时,默认监听器执行超过 60s 时会打印该日志。


通过阅读 Nacos 的日志,可以排查在使用 Nacos 配置中心过程遇到的问题,比如通过日志判断应用程序是否连接到了正确的 Nacos 服务端地址,是否监听了正确的 namespace,dataId 以及 group,是否正常收到了变更推送以及监听器回调时是否存在异常报错以及阻塞超时的情况。


在启动和运行时我们也可以在 Nacos 的 config.log 日志中观察到 Nacos 和 KMS 交互的日志,以便于更好地排查遇到的问题,关于集成 KMS 实现配置加解密的原理,可以参考《Nacos 安全零信任实践》一文中 Nacos 存储安全一节。


结语


以上我们在 Spring Cloud 应用中结合 Nacos 实现了运行期配置动态更新的功能,以及在此基础上结合 KMS 在不改动代码的情况下对应用使用的敏感配置进行保护,解决将配置迁移到 Nacos 中可能存在的数据安全顾虑,并对其底层工作原理做了简单介绍。Nacos 作为广泛使用的配置中心,除了基础的配置实时动态更新的核心功能外,还支持配置监听查询(配置订阅节点查询),推送轨迹,标签灰度等进阶的提升易用性功能。


安全性方面,我们对普通业务配置和敏感配置进行了拆分,从应用程序侧解决了敏感数据泄漏的问题,除此之外,我们在 MSE 控制台中也会有针对不同账号设置细粒度的访问控制的功能,比如控制业务普通配置对应用开发开放访问,数据源秘钥等敏感数据只对运维人员开放,MSE Nacos 也可以支持该功能,对于访问控制部分,我们后续也会有文章进行单独介绍,可关注后续文章。


相关链接:

[1] Nacos 官网

https://nacos.io

[2] Nacos Github 主仓库

https://github.com/alibaba/nacos

[3] 生态组仓库

https://github.com/nacos-group

[4] Spring Cloud Alibaba

https://sca.aliyun.com/docs/2023/user-guide/nacos/quick-start/


Nacos 多语言生态仓库:

[1] Nacos-GO-SDK

https://github.com/nacos-group/nacos-sdk-go

[2] Nacos-Python-SDK

https://github.com/nacos-group/nacos-sdk-python

[3] Nacos-Rust-SDK

https://github.com/nacos-group/nacos-sdk-rust

[4] Nacos C# SDK

https://github.com/nacos-group/nacos-sdk-csharp

[5] Nacos C++ SDK

https://github.com/nacos-group/nacos-sdk-cpp

[6] Nacos PHP-SDK

https://github.com/nacos-group/nacos-sdk-php

[7] Rust Nacos Server

https://github.com/nacos-group/r-nacos


推荐阅读:MSE Nacos:解决敏感配置的安全隐患

Nacos 配置中心变更利器:自定义标签灰度

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
11天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
15天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
6天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。
|
11天前
|
人工智能 运维 双11
2024阿里云双十一云资源购买指南(纯客观,无广)
2024年双十一,阿里云推出多项重磅优惠,特别针对新迁入云的企业和初创公司提供丰厚补贴。其中,36元一年的轻量应用服务器、1.95元/小时的16核60GB A10卡以及1元购域名等产品尤为值得关注。这些产品不仅价格亲民,还提供了丰富的功能和服务,非常适合个人开发者、学生及中小企业快速上手和部署应用。
|
7天前
|
人工智能 自然语言处理 前端开发
用通义灵码,从 0 开始打造一个完整APP,无需编程经验就可以完成
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。本教程完全免费,而且为大家准备了 100 个降噪蓝牙耳机,送给前 100 个完成的粉丝。获奖的方式非常简单,只要你跟着教程完成第一课的内容就能获得。
|
1天前
|
云安全 存储 弹性计算
|
22天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3966 5
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
11天前
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
534 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
10天前
|
数据采集 人工智能 API
Qwen2.5-Coder深夜开源炸场,Prompt编程的时代来了!
通义千问团队开源「强大」、「多样」、「实用」的 Qwen2.5-Coder 全系列,致力于持续推动 Open Code LLMs 的发展。
|
18天前
|
安全 数据建模 网络安全
2024阿里云双11,WoSign SSL证书优惠券使用攻略
2024阿里云“11.11金秋云创季”活动主会场,阿里云用户通过完成个人或企业实名认证,可以领取不同额度的满减优惠券,叠加折扣优惠。用户购买WoSign SSL证书,如何叠加才能更加优惠呢?
999 3