Consul服务注册与发现

Consul服务注册与发现

1、为什么不再使用传统的Eureka?

  1. Eureka停更进维护;
  2. Eureka对初学者还是不太友好的,它还有自我保护模式;
  3. 注册中心独立且与微服务各功能解耦是大势所趋,目前主流服务中心,希望单独隔离出来而不是作为一个独立微服务嵌入到系统中,按照Netflix的之前的思路,注册中心Eureka也是作为一个微服务且需要程序员自己开发部署的,但是,目前我们更加得希望微服务和注册中心分离解耦,注册中心和业务无关的,不要混为一谈。想要提供类似tomcat一样独立的组件,微服务注册上去使用,是个成品,开箱即用。
  4. 阿里巴巴Nacos的崛起,既能做注册与发现又可以做分布式配置与管理,一个人可以干俩活,何乐而不为?用帕鲁不香嘛?

2、什么是Consul?

官网:Consul by HashiCorp

​ HashiCorp Consul 是一种服务网络解决方案,使团队能够管理服务之间以及跨本地和多云环境和运行时的安全网络连接。Consul 提供服务发现、服务网格、流量管理和网络基础设施设备的自动更新。您可以单独使用这些功能,也可以在单个 Consul 部署中一起使用这些功能。

能干什么?

  • 服务发现

    提供HTTP和DNS两种发现方式。

  • 健康监测

    支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控。

  • KV存储

    Key、Value的存储方式

  • 多数据中心

    Consul支持多数据中心

  • 可视化界面

Spring Cloud Consul:Spring Cloud Consul

image-20240309211718448

3、Consul下载

​ 下载连接Windows:下载 (hashicorp.com)

​ 下载完成后就只有一个consul.exe,在它的下载路径中我们打开命令框输入:

consul --version

​ 看到版本号输出即可。

image-20240310111726600

​ 然后我们使用开发者模式启动,输入以下内容:

consul agent -dev

image-20240310111919115

​ 然后浏览器通过地址:http://localhost:8500就可以访问到Consul的首页了

image-20240310112026984

4、服务注册与发现

4.1、服务提供者8001

​ 支付服务provider8001注册进consul

​ 在pom文件中导入SpringCloud Consul的依赖

<!--SpringCloud consul discovery -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

​ application.yml文件添加consul配置

  ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}

​ 然后修改主启动类,打上@EnableDiscoveryClient注解,开启服务发现

@MapperScan("com.zm.cloud.mapper")
@SpringBootApplication
@EnableDiscoveryClient
public class Main8001 {
    public static void main(String[] args) {
        SpringApplication.run(Main8001.class,args);
    }
}

​ 然后启动微服务,到consul界面查看,会有一点点的延迟,但很快

image-20240310132925846

​ 我们看一下后台,发现有一个提示,这个提示不影响程序正常运行,它让你移除commons-logging.jar,我们就在consul的依赖下移除它就好了。

Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts

​ 依赖变成这样

<!--SpringCloud consul discovery -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

​ 这样警告信息就没有了。

4.2、服务消费者80

​ 同样的方法先导依赖

<!--SpringCloud consul discovery -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

​ application.yml配置文件

spring:
  application:
    name: cloud-consumer-order
  ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true #优先使用服务ip进行注册
        service-name: ${spring.application.name}

​ 主启动类打上@EnableDiscoveryClient注解,开启服务发现。

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

​ 现在再来看一下原来我们写的硬编码问题,当时支付模块8001的地址写死了,看一下controller,做修改,我们要从Consul里获取8001的服务,就直接写成http://cloud-payment-service

//先写死,支付模块的地址
//private static final String PAY_MAN_SERVER = "http://localhost:8001";
private static final String PAY_MAN_SERVER = "http://cloud-payment-service";

​ 启动测试一下,获取一个信息

image-20240310142411983

image-20240310142437968

​ 发现报错了,为什么呢?

​ 因为Consul天生支持负载均衡的,消费者去调用支付服务模块,默认的它会认为支付模块是一个集群,如果直接通过微服务的名字进行调用,它就找不着这个服务从而报错。

​ 这里就需要我们去修改一下RestTemplateConfig了

@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced//打开支持负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
}

​ 这个注解是Spring Cloud特有的,用于开启客户端负载均衡。当RestTemplate被标记为@LoadBalanced时,它会使用Ribbon(或其他负载均衡器)来选择一个服务实例进行调用。这在微服务架构中特别有用,因为你可以有多个相同服务的实例运行在不同的服务器上,而@LoadBalancedRestTemplate会帮助你自动选择一个实例进行调用,没有打上这个注解之前它都只认地址加端口号去找服务提供者,我们写成服务名称当然找不着服务了。

​ 下面重启一下再试试

image-20240310144111930

​ 这下就查询到了,服务可用。

4.3、三个注册中心异同点

image-20240310150126132

CAP

  • CConsistency(强一致性);
  • AAvailability (可用性);
  • PPartition tolerance(分区容错性);

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好地满足两个。

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  • CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

image-20240310150047817

分析特点:

AP(Eureka)

​ AP架构

​ 当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。

​ 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性结论:违背了一致性C的要求,只满足可用性和分区容错,即AP;

image-20240310150413830

CP(Zookeeper/Consul)

​ CP架构

​ 当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性,Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。

​ 虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。

​ 结论:违背了可用性A的要求,只满足一致性和分区容错,即CP;

image-20240310150545473

5、分布式服务配置与刷新

​ 分布式系统面临的问题,就是配置问题。

​ 微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。比如某些配置文件中的内容大部分都是相同的,只有个别的配置项不同。就拿数据库配置来说吧,如果每个微服务使用的技术栈都是相同的,则每个微服务中关于数据库的配置几乎都是相同的,有时候主机迁移了,我们希望一次修改,处处生效。

​ 当下我们每一个微服务自己带着一个application.yml,上百个配置文件的管理非常繁琐。

​ 我们可用将通用的全局配置信息,直接注册进Consul,从Consul获取,既然要从Consul获取就得遵循Consul的配置规则要求。

​ 我们从官方文档中可以看到具体需要怎么做

image-20240310171402080

​ 官网中说,使用YAML格式来存储属性会更方便,可以通过设置spring.cloud.consul.config.format属性为YAMLPROPERTIES来选择使用哪种格式,如果你已经设置了spring.cloud.bootstrap.enabled=truespring.config.use-legacy-processing=true,或者包含了spring-cloud-starter-bootstrap依赖,那么配置值应该放在bootstrap.yml而不是application.yml中。

​ consul中配置属性的存储位置,yaml必须设置在consul中的适当键下,类似于这样:

config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data

image-20240310172116251

5.1、配置bootstrap.yml

​ 那么就先添加依赖,consul的服务配置

<!--SpringCloud consul config-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

​ 需要新建配置文件bootstrap.yml,啥是bootstrap.yml?

  • applicaiton.yml是用户级的资源配置项;
  • bootstrap.yml是系统级的,优先级更加高;

​ Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment

Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。 Bootstrap contextApplication Context有着不同的约定,所以新增了一个bootstrap.yml文件,保证Bootstrap ContextApplication Context配置的分离。**application.yml文件改为bootstrap.yml,这是很关键的或者两者共存。**因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml。

​ 那么接下来就开始写一下,bootstrap.yml文件

spring:
  application:
    name: cloud-payment-service
    ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      config:
        profile-separator: '-' #官网上默认的是逗号,这不符合我们的习惯,我们使用-号来做分割
        format: YAML
  
  # config/cloud-payment-service/data
  #       /cloud-payment-service-dev/data
  #       /cloud-payment-service-prod/data

​ 我们抽掉了和服务相关的配置项,那原来的application.yml就可以删除对应的部分了,同时我们要配置多环境配置加载内容dev,当然,不写就是默认的配置。

server:
  port: 8001

# ==========applicationName + druid-mysql8 driver===================
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    username: root
    password: 123456
  profiles:
    active: dev # 多环境配置加载内容dev/prod,不写就是默认default配置

# ========================mybatis===================
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.zm.cloud.entities
  configuration:
    map-underscore-to-camel-case: true

5.2、consul服务器key/value配置填写

​ 参考规则

# config/cloud-payment-service/data
#       /cloud-payment-service-dev/data
#       /cloud-payment-service-prod/data

​ 根据规则,创建config文件夹以/结尾

image-20240310193523308

​ 进去创建

image-20240310193620087

​ 然后就有config文件夹了

image-20240310193646862

​ 我们进入config文件夹,再分别创建以下几个文件:

  • cloud-payment-service;
  • cloud-payment-service-dev;
  • cloud-payment-service-prod;

image-20240310194157358

​ 然后在每一个目录下添加data数据。

image-20240310212520591

​ 创建完成后就可以在controller中写个测试,能从consul中拿到上面的data数据就可以了。

​ 现在是dev环境

image-20240310212936666

​ 改一下

profiles:
  active: prod # 多环境配置加载内容dev/prod,不写就是默认default配置

​ 再重启查看环境改变

image-20240310213128665

​ 再改一下,default就是不写。

image-20240310213244506

5.3、动态刷新

​ 我们目前在consul的dev配置分支修改环境的时候刷新马上访问结果,就会看到它实时的进行了更新。

​ 我们修改版本为2,刷新一下再看就变成了2版本

image-20240311093812071

image-20240311094852947

​ 按理讲,你可能会说,我都没有显示的配置consul进行动态刷新,它怎么就自己刷新了?这就consul内置的一些机制和功能了。

​ Consul通过不断地轮询其HTTP API来检测相关的配置目录是否发生了变化。当检测到配置目录发生变化时,Consul会自动触发配置的刷新操作。这种轮询的间隔时间通常是可配置的,例如,通过spring.cloud.consul.config.watch.wait-time参数可以设置默认的轮询间隔为1000毫秒。一般没有特别的需求是不需要更改的,我们来看一下官网怎么说的。

image-20240311095213872

​ 使用spring.cloud.consul.config.watch.delay参数就是1秒,这也是默认值。

​ 同时,还有一个wait-time属性,它设置调用consul的接口方法时会阻塞的指定时间。默认值是55秒,但这个时间需要小于60秒。如果在阻塞过程中有配置修改,则立马返回;否则,要等到阻塞时间结束。

​ 我们可以显示的配置动态刷新,需要在主启动类中打上动态刷新的注解。

@MapperScan("com.zm.cloud.mapper")
@SpringBootApplication
@EnableDiscoveryClient
@RefreshScope  //动态刷新
public class Main8001 {
    public static void main(String[] args) {
        SpringApplication.run(Main8001.class,args);
    }
}

​ 然后可以设置指定时间在bootstrap配置文件中,这里就设置3秒了。

spring:
  application:
    name: cloud-payment-service
    ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      config:
        profile-separator: '-' #官网上默认的是逗号,这不符合我们的习惯,我们使用-号来做分割
        format: YAML
        watch:
          wait-time: 3

​ 我们修改这个时间只是演示作用,实际没啥特殊需要就不要改。

​ 还有,这个时候如果你把consul给关闭了,那么你创建的config文件以及下面的所有配置都会清空的,之前在consul配置的都白配置了,所以我们需要解决一个consul配置持久化问题。

5.4、Consul配置持久化

​ 我们在consul的下载目录中,和consul.exe同级,分别创建一个名为data和myconfig文件夹。

image-20240311103407533

​ 然后启动的时候就可以选择这两个目录启动。

consul agent -server -bootstrap-expect 1 -ui -node=consul-dev  -data-dir=D:\Consul\consul_1.18.0_windows_amd64\data -config-dir=D:\Consul\consul_1.18.0_windows_amd64\myconfig -client=0.0.0.0  -bind=127.0.0.1  

​ 我们把之前的consul关闭,再使用以上命令启动,就会发现我们设置的config文件都还在,我们再想新增内容它也会保存下来,下次启动的时候选择data路径数据就会都在。

image-20240311104610513

​ 这样做只不过是我们自己手动指定目录的手动持久化,还有一种是自动的,需要我们在consul.exe同级目录下创建一个consul_start.bat文件,内容就是这样写,里面的data路径要写自己的:

@echo.service startup......  
@echo off  
@sc create Consul binpath= "D:\Consul\consul_1.18.0_windows_amd64\consul.exe agent -server -ui -bind=127.0.0.1 -client=0.0.0.0 -bootstrap-expect  1  -data-dir D:\Consul\consul_1.18.0_windows_amd64\data"
@net start Consul
@sc config Consul start= AUTO  
@echo.Consul starting success! 
@pause

​ 解释:

sc create :创建windows服务的命令
Consul :是我们的服务名
binPath:程序的一些路径和别的配置
	-client:改成自己的ip,本地就是0.0.0.0,如果是云服务器就写云服务器的公网IP
	-data-dir:数据持久化的数据存放在哪

​ 使用管理员运行,它就会创建一个系统服务,开机自启,其实就是把我们手动持久化启动consul的命令写到windows服务中,这样就不需要我们每一次都手动启动consul,一劳永逸的方法,有感兴趣的同学可以尝试,这里我就不再演示了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入理解java之网络编程

目录&#xff1a; 网络编程基本概念计算机网络网络通信协议数据封装与解封IP地址TCP协议和UDP协议 Java网络编程中的常用类InetAddress的使用InetSocketAddress的使用URL的使用TCP通信的实现和项目案例TCP通信入门案例UDP通信的实现和项目案例UDP通信入门案例 网络编程基本概念…

片上网络(NoC)技术的发展及其给高端FPGA带来的优势

片上网络(NoC)技术的发展及其给高端FPGA带来的优势 1. 概述 在摩尔定律的推动下,集成电路工艺取得了高速发展,单位面积上的晶体管数量不断增加。 片上系统(System-on-Chip,SoC)具有集成度高、功耗低、成本低等优势,已经成为大规模集成电路系统设计的主流方向,解决了…

自媒体新人该如何开始

作为一个准备踏入自媒体领域的新手&#xff0c;面对一片陌生的领域可能让你感到有点手足无措&#xff0c;就好比是第一次学游泳&#xff0c;心里有些许的恐惧和不确定。同样的&#xff0c;当你第一次学骑自行车&#xff0c;也是一样的陌生&#xff0c;如果学会这些并熟练之后&a…

一文了解原型和原型链

本文重点概念&#xff1a; 1、所有的对象都是new一个函数创建的 2、所有的函数都有一个属性prototype&#xff0c;称为函数原型 3、函数原型得到的这个对象都有一个属性constructor,指向该函数 4、所有的对象都有一个属性&#xff1a;隐式原型__proto__&#xff0c;隐式原型…

pyqt线程正确使用

PyQt之科学使用线程处理耗时任务以及线程通信方法 上面这篇文章看似很科学… 经过实际测试&#xff0c;需要按下面创建线程&#xff1a; self.work EmailWork() self.thread QtCore.QThread() self.thread.start()self.work.moveToThread(self.thread) self.work.complete_…

java应用整合fastdfs实现文件 上传及下载

java应用整合fastdfs实现文件 上传及下载 对于fastdfs的安装部署请参阅另一篇博文&#xff1a;fastdfs安装篇 本篇主要讲在springboot项目中如何整合fastdfs实现文件上传 下载 及删除&#xff0c; 项目demo gitee 地址&#xff1a;git clone https://gitee.com/JackSong2019/f…

C++第一弹---C++入门(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 【C详解】 C入门 1、C关键字(C98) 2、命名空间 2.1、命名空间定义 2.2、命名空间使用 3、C输入&输出 4、缺省参数 4.1、缺省参数概念 4.2、缺省参…

酷开科技利用自身优势量身定制个性化营销创意

随着人工智能、大数据、物联网、区块链等技术的发展&#xff0c;去中心化、碎片化、社交化、全链条可追踪的趋势将越来越明显。广告主对于投放的每一分钱都会有更高性价比、更精准效果的追求。业精于专成于势&#xff0c;酷开系统专注构建开放统一的超级智能系统生态&#xff0…

【题解】—— LeetCode一周小结10

【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结9 4.用栈实现队列 题目链接&#xff1a;232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a…

spring boot集成neo4j实现简单的知识图谱

一、neo4j介绍 随着社交、电商、金融、零售、物联网等行业的快速发展&#xff0c;现实社会织起了了一张庞大而复杂的关系网&#xff0c;传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随数据量呈几何级数增长&#xff0c;急需一种支持海量复杂数据关系运算的…

每日OJ题_链表⑤_力扣25. K 个一组翻转链表

目录 力扣25. K 个一组翻转链表 解析代码 力扣25. K 个一组翻转链表 25. K 个一组翻转链表 难度 困难 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总…

java集合类常用的方法介绍

在 Java 中&#xff0c;集合&#xff08;Collections&#xff09;是用于存储多个元素的容器。Java Collections Framework 提供了丰富的集合类&#xff0c;用于满足不同的数据存储需求。以下是一些常用的 Java 集合类及其常用方法&#xff0c;以及简单的例子来说明它们的用法。…

AI 对齐是未来十年最重要的科学和社会技术工程 | 新程序员

【导读】人工智能与机器学习技术犹如疾风骤雨般席卷全球&#xff0c;在颠覆传统的同时为人类带来了新一轮的伦理挑战。AI 模型虽能凭借强大的数据处理能力和优化效率在各个行业大放异彩&#xff0c;然而在追求极致准确性的模型行为背后&#xff0c;却存在与其设计初衷产生偏差的…

2024-03-10 c++

&#x1f338; MFC下拉框控件 | Combo Box eg 计算器 1。新建MFC项目&#xff08;基于对话框、静态库&#xff09; 2。添加控件&#xff0c;删除初始的3个多余控件 加3个edit control 加1个combo box&#xff0c;属性sort改为false&#xff0c;data为 ;-;;;% 加1个static text…

【数据结构】红黑树(C++实现)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.概念 2.性质 3.…

企业微信HOOK协议,新设备二次验证处理

提示设备强制二次验证问题已处理 HOOK&#xff1a;https://www.showdoc.com.cn/1663062930779972/7859611259700402密码&#xff1a;999999999

蓝桥杯练习系统(算法训练)ALGO-979 移动

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 给定一个n长的数列&#xff0c;有m次操作&#xff0c;第i次操作表示将整个数列循环移动mi位&#xff0c;询问每次操作结束后…

前端解决跨域问题( 6种方法 )

本专栏是汇集了一些HTML常常被遗忘的知识&#xff0c;这里算是温故而知新&#xff0c;往往这些零碎的知识点&#xff0c;在你开发中能起到炸惊效果。我们每个人都没有过目不忘&#xff0c;过久不忘的本事&#xff0c;就让这一点点知识慢慢渗透你的脑海。 本专栏的风格是力求简洁…

【MATLAB源码-第160期】基于matlab的胡桃夹子优化算法(NOA)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 胡桃夹子优化算法&#xff08;Nutcracker Optimization Algorithm, NOA&#xff09;是一个灵感来源于胡桃夹子的故事的元启发式优化算法。这个故事中&#xff0c;胡桃夹子是一个能够将坚果壳轻易地破开以获取内部果仁的工具。…