SpringCloud全家桶— — 【1】eureka、ribbon、nacos、feign、gateway

news2024/11/26 18:21:27

SpringCloud全家桶— — 组件搭建

1 Eureka

1.1 Eureka-server

创建eureka-server的SpringBoot项目

①导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

②启动类上添加注解@EnableEurekaServer

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

③编写配置文件,指明eureka地址

eureka本身也需要注册上去

server:
  port: 10086
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka

启动eureka所在SpringBoot项目,浏览器输入http://127.0.0.1:10086
在这里插入图片描述

1.2 Eureka-client

eureka作为注册中心,我们现在将服务注册到eureka

①导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

②编写配置文件

spring:
  application:
  # 服务名称
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

1.3 服务发现

现在有两个模块:user-service和order-service;我们都将他们注册到eureka,现在order-service通过RPC远程调用user-service

order-service与user-service注册到eureka过程同上
①order配置restTemplate

可以单独在一个配置类写,或者直接写到SpringBootApplication中,只要注入到Spring容器中就行

/**
  * 创建RestTemplate并注入Spring容器
  */
 @Bean
 @LoadBalanced
 public RestTemplate restTemplate() {
     return new RestTemplate();
 }

②service中注入restTemplate

restTemplate是Spring提供的给我们操作rest服务的客户端

@Autowired
private RestTemplate restTemplate;

public Order queryOrderById(Long orderId) {
    // 1.查询订单
    Order order = orderMapper.findById(orderId);
    // 2.利用RestTemplate发起http请求,查询用户
    // 2.1.url路径【需要使用userservice对应的服务名】
    String url = "http://userservice/user/" + order.getUserId();
    // 2.2.发送http请求,实现远程调用
    User user = restTemplate.getForObject(url, User.class);
    // 3.封装user到Order
    order.setUser(user);
    // 4.返回
    return order;
}

spring会自动帮助我们从eureka-server端,根据userservice这个服务名称,获取实例列表,而后完成负载均衡。

2 Ribbon(以restTemplate为例)

导入openfeign,openfeign中默认集成了ribbon

2.1 restTemplate集成ribbon

RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

①导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

②创建restTemplate,并添加上负载均衡注解

可以在启动类的main方法中创建,也可以单独写一个配置类,只要最后有bean标识被spring管理即可

 /**
  * 创建RestTemplate并注入Spring容器
  */
 @Bean
 @LoadBalanced
 public RestTemplate restTemplate() {
     return new RestTemplate();
 }

@LoadBalanced是以轮询方式访问

2.1 自定义负载均衡

有两种方式:
①定义一个新的IRule

@Bean
public IRule randomRule(){
    return new RandomRule();
}

无法精准对某个微服务进行处理

②在配置文件中编写

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

注意,一般用默认的负载均衡规则,不做修改。

  • Ribbon默认是懒加载,也就是第一次访问的时候才会创建LoadBalanceClient,这样会导致请求时间会变得很长
  • 推荐开启饥饿加载(项目启动时创建)
ribbon:
  eager-load:
    enabled: true
    clients: userservice

clients可以精准对某个微服务进行处理

3 Feign、OpenFeign

3.1 Feign

restTemplate是Spring提供给我们的用于调用rest服务的客户端

RestTemplate调用方式:
在这里插入图片描述

•代码可读性差,编程体验不统一
•参数复杂URL难以维护

说明:Feign是一个声明式的HTTP客户端
①导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

②开启注解

在SpringBootApplication上开启对应注解

@EnableFeignClients

③编写Feign的客户端

# userservice是服务名称
# @GetMapping()中填写对应controller访问路径
@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

Feign主要是通过SpringMVC的注解来声明远程调用信息

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值类型:User

④在service中调用feignClient

@Service
public class OrderService {
    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

引入Feign的步骤:

1. 导入依赖
2. 添加@EnableFeignClients注解
3. 编写FeignClient接口
4. service中调用feignClient

Feign可以支持很多自定义配置

  • 修改日志级别
  • 响应结果的解析器(如:解析json为java对象)
  • 请求参数编码(将请求参数编码,便于http发送请求)
  • 支持的注解格式
  • 失败重试机制(默认没有,但是会使用ribbon的重试)

一般情况下,默认值就能满足我们的使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可

修改feign的默认配置

以修改日志级别为例
方式1:修改配置文件

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是将default改为具体服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

方式2:编写代码

先声明一个类,然后声明一个Logger.Level的对象

日志配置类:

public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

全局生效:将其放到启动类的@EnableFeignClients这个注解中

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

局部生效:把它放到对应的@FeignClient这个注解中

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class) 

Feign的使用优化

提高Feign的性能主要手段就是使用连接池代替默认的URLConnection(不支持连接池)

  • 以Apache的HttpClient来演示

①引入依赖

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

②配置连接池(配置文件)

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

最佳使用Feign的编写方式

1. 继承方式

①定义API接口
②FeignClient和controller都继承该接口
在这里插入图片描述

简单、实现了代码共享;但是服务提供方和消费方紧耦合,参数列表中的注解映射不会继承,因此controller中必须再此声明方法、参数列表、注解

2. 抽取方式

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

  • 例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。

在这里插入图片描述

各个微服务引用feign-api模块,然后调用对应方法,直接接收返回值即可

注意:order-service模块引用feign-api之后需要修改order-service启动类上的扫描包路径

  • 因为UserClient现在在cn.itcast.feign.clients包下
  • 而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。
# 方法1:指定扫描的包
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

# 方法2:指定需要加载的Client接口
@EnableFeignClients(clients = {UserClient.class})

4 Nacos

详细链接:https://editor.csdn.net/md/?articleId=126063863

4.1 nacos注册管理

①引入依赖

# 在父pom中引入
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
# 在微服务中引入
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

②微服务配置文件中配置nacos地址

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

③启动类上添加注解

@EnableDiscoveryClient//要注册服务到nacos必须加该注解

4.2 nacos其他功能

  1. 分级存储模型

为了灾备,防止"鸡蛋都碎在一个篮子里"

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称
  1. 设置集群负载均衡
userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 
  1. 设置权重
    在这里插入图片描述
  2. 环境隔离

namespace

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ
        namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID

4.3 nacos与eureka对比

在这里插入图片描述

  • 共同点:
  1. 都支持服务注册和拉取
  2. 都支持服务提供者采用心跳方式做健康检测
  • 区别:
  1. nacos支持服务端主动检测服务提供者状态。临时实例采用心跳模式,非临时实例采用主动检测模式
  2. nacos临时实例不正常会剔除,非临时实例则不剔除
  3. nacos支持服务列表变更推送
  4. Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

4.4 nacos配置管理

  1. 依赖

在对应微服务中引入依赖

<!--nacos配置管理依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
  1. 创建bootstrap.yml文件【优先级比application.yml高】

指明nacos中的配置文件名称和地址

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

5 服务网关

  • 网关作用:
  1. 请求路由
  2. 权限控制
  3. 限流
  • SpringCloud中的网关:
  1. gateway
  2. zuul
    Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

详细文章:https://editor.csdn.net/md/?articleId=127762843

5.1 搭建网关(以gateway为例)

①依赖

引入gateway依赖同时将网关服务注册到nacos中

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

②配置文件

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

我们将符合Path 规则的一切请求,都代理到 uri参数指定的地址。

本例中,我们将 /user/**开头的请求,代理到lb://userservice,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。

总结:搭建步骤
①引入nacos和gateway依赖
②配置application.yml,包括服务基本信息、nacos地址、路由
③路由信息包括:路由id、路由目标(uri)、路由断言(predicates)、路由过滤器(filters)

5.2 断言工厂

如:上面我们使用的path,是断言工厂中的一个。下面还有其他的:

  • After(是某个时间点后的请求)
  • Before(某个节点之前)
  • Between(是某两个时间点之前的请求)
  • Cookie(请求必须包含某些cookie)
  • Header(请求必须包含某些header)
  • Host(请求必须是访问某个host(域名))
  • Method(请求方式必须是指定方式)
  • Path(请求路径必须符合指定规则)
  • Query(请求参数必须包含指定参数)
  • RemoteAddr(请求者的ip必须是指定范围)
  • Weight(权重处理)

5.3 过滤器工厂

修改application.yml配置文件即可
需求:给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
        #default-filters: # 默认过滤项
      	# - AddRequestHeader=Truth, Itcast is freaking awesome! 

当前过滤器写在userservice路由下,因此仅仅对访问userservice的请求有效。

5.4 全局过滤器

在filter中编写自定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等

自定义全局过滤器:

需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有authorization,
  • authorization参数值是否为admin
    如果同时满足则放行,否则拦截
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

5.5 跨域问题

跨域问题:

域名、端口、协议三者任一一个不同
No access control allow origin

直接通过配置文件解决跨域问题:

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python实战】2023关键词是小孩儿?某歌结婚生女一步到位,Hu歌官宣已婚产女后的W博,笑死哈哈哈哈(爬虫+数据可视化)

前言 办公室里很多喜欢Hu歌的小姑娘&#xff0c;听说他结婚了&#xff0c;而且孩子都生了&#xff0c;都非常惊讶。 就是我也是今天才知道的&#xff0c;哈哈哈哈&#xff08;交通闭塞了些&#xff09;&#x1f602;&#x1f602;。 所有文章完整的素材源码都在&#x1f447;…

Java常见知识点汇总

Java常见知识点汇总基础概念与常识1.Java 语言有哪些特点?2.JVM vs JDK vs JRE3.什么是字节码?采用字节码的好处是什么?4.为什么不全部使用 AOT 呢&#xff1f;5.为什么说 Java 语言“编译与解释并存”&#xff1f;6.Oracle JDK vs OpenJDK7.Java 和 C 的区别?基本语法1.注…

codeforces周赛div3#855记录

目录 总结 一&#xff0c;A. Is It a Cat? 二&#xff0c;B. Count the Number of Pairs 三&#xff0c;C1. Powering the Hero (easy version) 四&#xff0c;C2. Powering the Hero (hard version) 总结 真羡慕ACM校队的同学&#xff0c;能AC七八题&#xff0c;甚至ak …

飞天云动,站在下一个商业时代的门口

ChatGPT的爆火让AIGC再度成为热词&#xff0c;随之而来的是对其商业化的畅想——不是ChatGPT自身如何盈利&#xff0c;而是它乃至整个AIGC能给现在的商业环境带来多大改变。 这不由得令人想起另一个同样旨在改变世界的概念&#xff0c;元宇宙。不同的是&#xff0c;元宇宙更侧…

Apache Flink 1.16 功能解读

摘要&#xff1a;本文整理自阿里云高级开发工程师 Apache Flink Committer、Flink 1.16 Release Manager 黄兴勃&#xff08;断尘&#xff09;&#xff0c;在 FFA 2022 核心技术专场的分享。本篇内容主要分为四个部分&#xff1a;综述持续领先的流处理更稳定易用高性能的批处理…

传输线的物理基础(一):地、信号和均匀传输线

我们每天都听到用到传输线&#xff0c;那么什么是传输线呢&#xff1f;一条同轴线缆是传输线&#xff0c;多层PCB板中带参考平面的PCB走线是传输线&#xff0c;我们可以理解为&#xff0c;传输线由任意两个具有长度的导体组成。接下来我们会看到&#xff0c;一条传输线用来将信…

想象力训练

一、课程目的1、了解想象力2、想象力训练二、静态想象法常用在单一图片上&#xff0c;比如一辆自行车要点1、形象鲜明 (大脑中生动的展现它的样子)2、放大:一点点放大它(后续的课程讲解经常用到放大这个方法)3、缩小:一点一点缩小它4、变多:一个变两个&#xff0c;两个变三个&a…

C++---数字三角形模型---传纸条(每日一道算法2023.2.26)

注意事项&#xff1a; 本题dp思路与 “线性dp–方格取数” 一致&#xff0c;下方思路仅证明为什么使用方格取数的思路是正确的。 题目&#xff1a; 小渊和小轩是好朋友也是同班同学&#xff0c;他们在一起总有谈不完的话题。 一次素质拓展活动中&#xff0c;班上同学安排坐成…

安卓开发调试使用 Charles抓包Https请求

1、Windows电脑安装证书Help->SSL Proxying -> Install Charles Root Certificate2、手机安装证书证书保存到电脑上.crt结尾的文件Help->SSL Proxying -> Save Charles Root Certificate2.复制到手机上 3.安装证书以红米手机为例打开手机设置-->密码与安全-->…

php宝塔搭建部署实战多模板cms管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的多模板cms管理系统源码。感兴趣的朋友可以自行下载学习。 技术架构 PHP7.0 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&#xff0c;宝塔添加一…

在软件开发中如何将看板方法与 Scrum 集合使用?

什么是看板和 Scrum 的混合模式&#xff1f;适合在哪些场景使用&#xff1f;有哪些成功的案例可参考&#xff1f;本文将围绕以上问题展开。敏捷实践是一个团队过程&#xff0c;选择适合团队的敏捷框架时并没有什么技巧&#xff0c;无论您是使用看板方法、Scrum 还是两者的组合&…

【C++】vector的模拟实现(SGI版本)

吃不了自律的苦&#xff0c;又接受不了平庸的罪。想让自己变好&#xff0c;但又想舒服些。 你啊你……要么就不要去想&#xff0c;想了又不去做&#xff0c;犹犹豫豫&#xff0c;徘徊不前&#xff0c;患得患失… 文章目录一、四种构造函数1.vector的框架和无参构造2.构造函数调…

为什么FPGA在深度学习领域有着得天独厚的优势?

01 FPGA在深度学习领域有哪些优势 FPGA&#xff08;Field-Programmable Gate Array&#xff09;是一种灵活的可编程硬件设备&#xff0c;它在深度学习应用领域中具有许多优势。 首先&#xff0c;FPGA具有非常高的并行性。在深度学习中&#xff0c;许多计算都可以并行化&…

Verilog实现组合逻辑电路

在verilog 中可以实现的数字电路主要分为两类----组合逻辑电路和时序逻辑电路。组合逻辑电路比较简单&#xff0c;仅由基本逻辑门组成---如与门、或门和非门等。当电路的输入发生变化时&#xff0c;输出几乎&#xff08;信号在电路中传递时会有一小段延迟&#xff09;立即就发生…

sqlserver数据库备份策略及实战测试

文章目录启动SQL SERVER 代理服务配置完整备份差异备份和事务日志备份备份还原测试测试云端备份最近研究sqlserver数据库备份&#xff0c;这里吧测试过程总结分享&#xff01;sqlserver日志备份主要分为三种 &#xff1a;全量备份、差异备份、事务日志备份。全量备份&#xff1…

大话数据结构-线性表

1 定义 线性表是零个或多个数据元素的有限序列。 2 抽象数据类型 ADT 线性表(List)Data&#xff1a;线性表的数据对象集合为{al,a2,a3,....an}&#xff0c;每个元素的类型均为DataType。其中&#xff0c;除第一个元素a1外&#xff0c;每一个元素有且只有一个直接前驱元素&…

锁屏面试题百日百刷-Hive篇(八)

锁屏面试题百日百刷&#xff0c;每个工作日坚持更新面试题。锁屏面试题app、小程序现已上线&#xff0c;官网地址&#xff1a;https://www.demosoftware.cn。已收录了每日更新的面试题的所有内容&#xff0c;还包含特色的解锁屏幕复习面试题、每日编程题目邮件推送等功能。让你…

gitblit 安装使用

1 安装服务端 简而言之&#xff1a;需要安装 java&#xff0c;gitblit&#xff0c; git 三个软件 Windows 10环境使用Gitblit搭建局域网Git服务器 前言 安装Java并配置环境安装gitblit并配置启动gitblit为windows服务使用gitblit创建repository并管理用户 1.1 安装Java并配…

[Java·算法·中等]LeetCode215. 数组中的第K个最大元素

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2分析思路3题解3&#x1f449;️ 力扣原文 题目 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不…

REFL: 联邦学习中智能的设备选择方法

原创 齐天宇 隐私计算研习社 收录于合集#联邦学习54个现有的FL方案使用随机的参与者选择来提高选择过程的公平性&#xff0c;但是这会导致资源的低效利用和较低的训练质量。本文系统地解决了FL中资源效率低效的问题&#xff0c;展示了智能参与者选择和合并来自落后参与者的更新…