当前位置: 首页 > news >正文

SpringCloud(二)--SpringCloud服务注册与发现

一. 引言

​ 前文简单介绍了SpringCloud的基本简介与特征,接下来介绍每个组成部分的功能以及经常使用的中间件。本文仅为学习所用,联系侵删。

二. SpringCloud概述

2.1 定义

​ Spring Cloud是一系列框架的有序集合,它巧妙地利用了Spring Boot的开发便利性来简化分布式系统基础设施的开发。在微服务架构中,许多复杂且繁琐的分布式系统问题,如服务发现注册、配置中心、消息总线、负载均衡、熔断机制以及数据监控等,通过Spring Cloud都可以以Spring Boot的开发风格进行快速实现,并做到一键启动和部署。这使得开发者能够更专注于业务逻辑的实现,而无需在底层技术上花费过多精力。

image

image.gif

三. SpringCloud核心组件与原理

3.1 服务注册与发现

3.1.1概念

​ 在微服务架构中,服务注册与发现是确保服务间正常通信的关键环节。服务提供者启动时,会将自己的网络地址、端口号等信息注册到注册中心,如Eureka、Consul或Zookeeper等。这些注册中心负责存储和维护服务的注册信息,并提供服务发现的功能。服务消费者通过注册中心查询所需服务的信息,包括服务的地址和端口等,从而实现服务的动态发现。

​ 服务注册与发现机制的实现,使得微服务架构中的服务能够动态地加入和退出系统,无需手动配置服务间的依赖关系。这大大提高了系统的可扩展性和可维护性。

3.1.2 常用中间件

​ 服务注册与发现通常通过Eureka,Zookeeper,Consul,Nacos等来实现。服务提供者将自己的信息注册到对应的服务端上,服务消费者从对应的服务端获取服务提供者的信息。

3.1.2.1 Eureka

​ Eureka是由Netflix开发并开源的服务发现框架,它主要用于定位运行在AWS域中的中间层服务,实现负载均衡和中间层服务故障转移。Spring Cloud将其集成在其子项目spring-cloud-netflix中,以实现Spring Cloud的服务发现功能。Eureka包含两个组件:Eureka Server和Eureka Client。

Eureka的主要功能和特点包括:
  1. 服务注册与发现:服务提供者在启动时向Eureka Server注册自己的信息,Eureka Server保存这些信息。服务消费者可以通过Eureka Server查询服务提供者的信息,实现动态服务发现。
  2. 客户端负载均衡:Eureka集成了Ribbon实现客户端负载均衡,减少服务间的耦合。
  3. 故障转移:Eureka可以发现服务的可用性,并在服务不可用时进行故障转移,保证系统的高可用性。
  4. 可扩展性:支持多种服务注册和发现策略,支持集群部署。
  5. 健康检查:Eureka有一个检测心跳的功能,服务提供者每30秒向Eureka Server发送心跳请求,报告健康状态。如果超时则会剔除掉这个服务的信息。
  6. 自我保护模式:Eureka Server提供了自我保护机制,当Eureka Server在短时间内丢失过多心跳时,会进入自我保护模式,不再剔除任何服务实例,以避免因网络问题导致的服务不可用。
  7. 心跳机制:服务提供方与Eureka之间通过“心跳”机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除,这就实现了服务的自动注册、发现、状态监控。
  8. 集群部署:Eureka Server可以构建集群,不同Eureka Server之间会进行服务信息同步,用来保证服务信息的一致性。

​ Eureka是微服务架构中服务注册与发现的重要组件,它通过简化服务间的通信,提高了系统的可扩展性和可维护性。尽管Eureka 2.0已经停止维护,但它仍然被许多公司的微服务系统所使用。

服务提供者注册代码示例

@SpringBootApplication  
@EnableEurekaClient  
public class ServiceProviderApplication {  public static void main(String[] args) {  SpringApplication.run(ServiceProviderApplication.class, args);  }  
}  // application.yml配置Eureka Server地址  
eureka:  client:  serviceUrl:  defaultZone: http://localhost:8761/eureka/

服务消费者发现代码示例

@RestController  
public class ServiceConsumerController {  @Autowired  private DiscoveryClient discoveryClient;  @GetMapping("/services")  public List<String> getServices() {  return discoveryClient.getServices();  }  
}  // application.yml配置Eureka Server地址  
eureka:  client:  serviceUrl:  defaultZone: http://localhost:8761/eureka/
3.1.2.2 Nacos
Nacos的功能与特点

​ Nacos是一个开源的动态服务发现、配置管理和服务管理平台,主要用于构建云原生应用。以下是Nacos的一些核心功能和特点:

  1. 服务发现与管理
    • Nacos支持基于DNS或RPC的服务发现,允许跨语言和跨平台的服务注册,并且客户端能够自动发现新注册的服务。
    • 提供对服务实例的健康状况监控,支持多种协议(如HTTP, TCP)的心跳检测,确保只有健康的实例参与服务调用。
    • 允许为每个服务实例附加额外的信息,如权重、版本等。
  2. 动态配置服务
    • 提供集中化的配置管理,支持实时更新并推送到所有订阅的客户端。
    • 支持多环境配置,可以针对不同的环境(开发、测试、生产)设置不同的配置值。
    • 配置热更新,即配置发生变化时,不需要重启服务即可生效,实现无缝的配置更新。
  3. DNS服务
    • 支持将服务名称解析为实际的IP地址,适用于微服务架构下的服务间通信。
    • 提供灵活的路由策略,可以根据需要设置负载均衡策略和其他路由规则。
  4. API和SDK支持
    • 提供Java、Python、Go等多种语言的客户端库,方便不同技术栈的应用集成Nacos。
    • 通过RESTful风格的API,用户可以直接操作Nacos中的数据和服务。
  5. 可视化控制台
    • 提供了一个Web控制台,便于管理员查看集群状态、管理服务实例、修改配置等。
    • 支持基于角色的访问控制(RBAC),可以精细控制用户的访问权限。
  6. 高可用性
    • 支持在多个节点上部署以形成集群,保证系统的高可用性和容错能力。
    • 使用数据库或磁盘文件存储关键数据,即使服务器宕机也能恢复服务状态。
  7. 其他特性
    • 与Spring Cloud生态系统良好集成,同时也支持其他主流的微服务框架。
    • 支持SSL/TLS加密传输,保护敏感信息的安全。

​ Nacos的这些功能使其成为构建微服务架构中不可或缺的一部分,特别是在大规模分布式系统中,它可以极大地简化服务治理和配置管理工作。

一句话概括就是Nacos = SpringCloud注册中心 + SpringCloud配置中心

Nacos配置示例

服务提供者配置(application.yml):

server:port: 8070
spring:application:name: nacos-providercloud:nacos:discovery:server-addr: 127.0.0.1:8848 # Nacos服务地址

服务消费者配置(application.yml):

server:port: 8071
spring:application:name: nacos-consumercloud:nacos:discovery:server-addr: 127.0.0.1:8848 # Nacos服务地址

启动类注解:

@SpringBootApplication
@EnableDiscoveryClient //开启服务注册发现功能
public class NacosProviderApplication {public static void main(String[] args) {SpringApplication.run(NacosProviderApplication.class, args);}
}

详情参考:https://blog.csdn.net/wuesr/article/details/119032757

3.1.2.3 Zookeeper
Zookeeper功能与特点

​ Zookeeper是一个开源的分布式协调服务,由Apache基金会维护。它最初是作为Hadoop和Hbase的一个组件开发的,用于管理集群中的配置信息、命名服务、分布式同步和群组服务等。以下是Zookeeper的一些关键特点:

  1. 数据模型:Zookeeper提供了一个树状的层次化命名空间,称为ZNode,类似于文件系统。每个ZNode都可以存储数据,但有1MB的数据大小限制。
  2. 通知机制:客户端可以对特定的ZNode设置Watcher,当ZNode发生变化时,客户端会收到通知,从而可以做出相应的业务调整。
  3. 一致性:Zookeeper保证了全局数据的一致性,即所有服务器保存的数据副本都是相同的。
  4. 顺序性:Zookeeper中的更新请求是顺序进行的,来自同一个客户端的更新请求会按照发送顺序依次执行。
  5. 原子性:数据更新是原子性的,要么成功,要么失败。
  6. 实时性:在一定时间范围内,客户端能够读取到最新的数据。

​ Zookeeper广泛应用于分布式系统中,用于实现数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。

Zookeeper配置示例

Maven依赖:

<!-- zookeeper支持 -->
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.6.4</version>
</dependency>
<!-- curator-recipes -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.5.0</version>
</dependency>
<!-- curator-framework -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.5.0</version>
</dependency>

连接Zookeeper客户端:

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
CuratorFramework client = CuratorFrameworkFactory.newClient("ip:port",1000,60*1000,retryPolicy);
client.start();

详情参考:(https://blog.csdn.net/weixin_64105389/article/details/134180897)

3.1.2.4 Consul

Consul是由HashiCorp开发的开源工具,用于实现分布式系统的服务发现和配置。Consul的特点包括:

  1. 服务发现:Consul通过DNS或HTTP接口简化了服务的注册和发现过程,允许外部服务同样注册。
  2. 健康检查:Consul集成了健康检查功能,可以快速告警集群中的操作问题,并防止服务转发到故障的服务上。
  3. 键/值存储:Consul提供了一个动态配置存储系统,通过简单的HTTP接口可以在任何地方操作。
  4. 多数据中心支持:Consul无需复杂配置即可支持任意数量的数据中心。
  5. 安全性:Consul提供了ACL(访问控制列表)和TLS加密,以确保服务间通信的安全。

​ Consul的架构由服务器(SERVER)和客户端(CLIENT)节点组成,所有服务都可以注册到这些节点上,实现服务注册信息的共享。Consul的设计目标是对DevOps社区和应用程序开发人员友好,适合现代化、弹性基础架构的需求。

Consul配置示例
Maven依赖

首先,你需要在你的pom.xml文件中添加Consul客户端的依赖。这里使用的是consul-apiconsul-session客户端库。

xml

<dependencies><!-- Consul API --><dependency><groupId>com.orbitz.consul</groupId><artifactId>consul-client</artifactId><version>1.4.2</version></dependency><!-- Consul Session --><dependency><groupId>com.orbitz.consul</groupId><artifactId>consul-session</artifactId><version>1.4.2</version></dependency>
</dependencies>
服务注册
import com.orbitz.consul.Consul;
import com.orbitz.consul.model.agent.ImmutableRegistration;
import com.orbitz.consul.model.agent.Registration;public class ConsulServiceRegistration {public static void main(String[] args) {// 创建Consul实例,连接到本地Consul代理Consul consul = Consul.builder().build();// 构建服务注册信息Registration registration = ImmutableRegistration.	builder().id("service-id") // 服务ID.name("my-service") // 服务名称.address("127.0.0.1") // 服务地址.port(8080) // 服务端口.check(Registration.RegCheck.http("http://127.0.0.1:8080/health", "10s")) // 健康检查.build();// 注册服务consul.agentClient().register(registration);System.out.println("Service registered with Consul");}
}
服务注销
import com.orbitz.consul.Consul;
import com.orbitz.consul.model.agent.Deregistration;public class ConsulServiceDeregistration {public static void main(String[] args) {// 创建Consul实例,连接到本地Consul代理Consul consul = Consul.builder().build();// 构建服务注销信息Deregistration deregistration = Deregistration.builder().id("service-id") // 服务ID.build();// 注销服务consul.agentClient().deregister(deregistration);System.out.println("Service deregistered from Consul");}
}
服务发现
import com.orbitz.consul.Consul;
import com.orbitz.consul.model.catalog.CatalogService;import java.util.List;public class ConsulServiceDiscovery {public static void main(String[] args) {// 创建Consul实例,连接到本地Consul代理Consul consul = Consul.builder().build();// 获取所有服务List<CatalogService> services = consul.catalogClient().getServices().getResponse();// 打印服务名称for (CatalogService service : services) {System.out.println(service.getServiceName());}}
}
3.1.2.5 总结

img

参考资料:

eureka、consul、nacos三大产品对比 - ☆野生架构师☆ - 博客园

).getServices().getResponse();

    // 打印服务名称for (CatalogService service : services) {System.out.println(service.getServiceName());}
}

}


#### 3.1.2.5 总结[外链图片转存中...(img-7K64nSwU-1735826422036)]参考资料:[eureka、consul、nacos三大产品对比 - ☆野生架构师☆ - 博客园](https://www.cnblogs.com/shumtn/p/13391470.html)

相关文章:

SpringCloud(二)--SpringCloud服务注册与发现

一. 引言 ​ 前文简单介绍了SpringCloud的基本简介与特征&#xff0c;接下来介绍每个组成部分的功能以及经常使用的中间件。本文仅为学习所用&#xff0c;联系侵删。 二. SpringCloud概述 2.1 定义 ​ Spring Cloud是一系列框架的有序集合&#xff0c;它巧妙地利用了Spring…...

国内Ubuntu环境Docker部署CosyVoice

国内Ubuntu环境Docker部署CosyVoice 本文旨在记录在 国内 CosyVoice项目在 Ubuntu 环境下如何使用 dockermin-conda进行一键部署。 源项目地址&#xff1a; https://github.com/FunAudioLLM/CosyVoice 如果想要使用 dockerpython 进行部署&#xff0c;可以参考我另一篇博客中的…...

嵌入式linux系统中QT信号与槽实现

第一:Qt中信号与槽简介 信号与槽是Qt编程的基础。因为有了信号与槽的编程机制,在Qt中处理界面各个组件的交互操作时变得更加直观和简单。 槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。 案例操作与实现: #ifndef …...

科研绘图系列:R语言单细胞数据常见的可视化图形

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理图1图2图3图4图5图6系统信息参考介绍 单细胞数据常见的可视化图形 因为本教程是单细胞数据,因此运行本画图脚本需要电脑的内存最少32Gb 加载…...

使用 C++ 和函数式编程构建高效的 AI 模型

引言 现代 AI 开发常常使用 Python&#xff0c;但在底层实现中&#xff0c;C 仍是不可或缺的语言&#xff0c;尤其是在性能敏感的场景下。将 C 与函数式编程结合&#xff0c;可以打造高效、模块化的 AI 模型&#xff0c;同时提高代码的可读性和可维护性。本文将深入探讨如何利用…...

guestfish/libguestfs镜像管理工具简介

文章目录 简介guestfishlibguestfs项目 例子原理代码libguestfs架构参考 简介 guestfish Guestfish 是libguestfs项目中的一个工具软件&#xff0c;提供修改虚机镜像内部配置的功能。它不需要把虚机镜像挂接到本地&#xff0c;而是为你提供一个shell接口&#xff0c;你可以查…...

如何在centos中进行有效的网络管理

如何在centos中进行有效的网络管理&#xff1f; 在CentOS中&#xff0c;网络管理是系统管理员日常工作的重要组成部分&#xff0c;本文将详细介绍CentOS中的两种主要网络管理工具&#xff1a;传统的network服务和新一代的NetworkManager&#xff0c;帮助读者更好地配置和管理C…...

Oracle清空表后如何恢复数据

有时候忘记备份数据&#xff0c;把数据清空了&#xff0c;或者删除了&#xff0c;这时候怎么恢复数据呢&#xff0c;使用下面sql即可&#xff0c;替换对应的table和column INSERT INTO table1(column1,column2,column3 ) SELECTcolumn1,column2,column3 FROMtable1 AS OF time…...

ElasticSearch基础-文章目录

ElasticSearch学习总结1&#xff08;环境安装&#xff09; ElasticSearch学习总结2&#xff08;基础查询&#xff09; ElasticSearch学习总结3&#xff08;.NetCore操作ES&#xff09; ElasticSearch学习总结4&#xff08;sql操作ES&#xff09; ElasticSearch学习总结5&am…...

SpringMVC(二)原理

目录 一、配置Maven&#xff08;为了提升速度&#xff09; 二、流程&&原理 SpringMVC中心控制器 完整流程&#xff1a; 一、配置Maven&#xff08;为了提升速度&#xff09; 在SpringMVC&#xff08;一&#xff09;配置-CSDN博客的配置中&#xff0c;导入Maven会非…...

Selenium 自动化,如何下载正确的 ChromeDriver

在 Python 的 Selenium 自动化操作中&#xff0c;chromedriver 是不可或缺的驱动程序。没有正确安装对应版本的驱动&#xff0c;运行代码时常常会遇到报错问题&#xff0c;比如 “session not created: This version of ChromeDriver only supports Chrome version XX”。 今天…...

[Linux]redis5.0.x升级至7.x完整操作流程

1. 从官网下载最新版redis&#xff1a; 官网地址&#xff1a;https://redis.io/download 注&#xff1a;下载需要的登录&#xff0c;如果选择使用github账号登录&#xff0c;那么需要提前在github账号中取消勾选“Keep my email addresses private”&#xff08;隐藏我的邮箱…...

Java字符编码与正则表达式深度解析

Java字符编码与正则表达式深度解析 1. 字符编码发展 1.1 ASCII 码 在计算机最初发明时&#xff0c;主要用于数值计算&#xff0c;但随着计算需求的增加&#xff0c;人们发现计算机可以用来处理文本信息。因此&#xff0c;将字符映射为数字来表示。 字母 ‘A’ 映射为 65&am…...

【C++】B2099 矩阵交换行

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目描述输入格式输出格式输入输出样例输入 #1输出 #1 &#x1f4af;题目分析&#x1f4af;不同解法分析我的做法实现步骤&#xff1a;优点&#xff1a;不足&#…...

论文解读 | NeurIPS'24 IRCAN:通过识别和重新加权上下文感知神经元来减轻大语言模型生成中的知识冲突...

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 作者简介 史丹&#xff0c;天津大学博士生 内容简介 大语言模型&#xff08;LLM&#xff09;经过海量数据训练后编码了丰富的世界知识。最近的研究表明&#xff0c…...

edeg插件/扩展推荐:助力生活工作

WeTab 此插件在我看来有2个作用 1.改变edeg的主页布局和样式,使其更加精简,无广告 2.提供付费webtab Ai(底层是chatGpt) 沉浸式翻译 此插件可翻译网页的内容 假设我们浏览github 翻译前 翻译后 Better Ruler 可以对网页的距离进行测量 适合写前端的小伙伴 用法示例:...

基于Python读取ZIP和TAR格式压缩包教程

在数据处理和文件管理中&#xff0c;压缩包&#xff08;如ZIP、TAR等格式&#xff09;的使用非常普遍。Python提供了多种库来读取和处理这些压缩包。本文将介绍如何使用Python的内置库和第三方库来读取ZIP和TAR格式的压缩包。 1、读取ZIP文件 Python的zipfile模块提供了处理Z…...

懒人不下床型遥控方案--手机对电脑的简单遥控(无收费方案)

兄弟们&#xff0c;天气越发寒冷&#xff0c;不得不说&#xff0c;对像我这种喜欢看直播睡觉的懒狗越发的不友好了&#xff0c;每次昏昏欲睡但还要下床关直播的操作就像泡完温泉直接冲凉水澡&#xff0c;透心凉&#xff0c;心飞扬。 最进也是有时间找找合适的懒人方案解决这个…...

人工智能知识分享第八天-机器学习_泰坦尼克生存预估线性回归和决策树回归对比案例

泰坦尼克生存预估案例 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import classification_report import matplotlib.pyplot as plt from sklearn.tree import plot_t…...

html中下拉选框的基本实现方式及JavaScript动态修改选项内容情况总结

最近项目中使用到了下拉选项以及通过js判断动态改变选项值的相关操作&#xff0c;查询了一些相关内容&#xff0c;在此记录一下&#xff0c;以免后续再碰到布置如何书写。 一、html中下拉选框的基本方式 在 HTML 中&#xff0c;创建下拉选择框&#xff08;也叫选择菜单&#…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...