微服务篇之Nacos快速入门

Nacos 简介

Nacos 起源

Nacos 起源于阿里巴巴 2008 年的五彩石项目(完成微服务拆分和业务中台建设),经历了阿里十年双十⼀的洪峰流量的考验,沉淀了简单易用、稳定可靠、性能卓越等核心特性。随着云计算的兴起和受到开源软件行业的影响,2018年阿里决定将Nacos(阿里内部Configserver/Diamond/Vipserver 内核) 开源,输出阿里十年的沉淀,推动微服务行业发展,加速企业数字化转型!

Nacos 定位

Nacos/nɑ:kəʊs/Dynamic Naming and Configuration Service 的首字母简称;⼀个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

官网:https://nacos.io/ 仓库:https://github.com/alibaba/nacos

Nacos 功能

1. 服务发现和服务运行状况检查: Nacos使服务可以通过DNS或HTTP接口简单地注册自己并发现其他服务。Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。

2. 动态配置管理: 动态配置服务允许您以集中和动态的方式跨所有环境管理所有服务的配置。Nacos消除了在更新配置时重新部署应用程序和服务的需要,这使得配置更改更加高效和敏捷。

3. 动态DNS服务: Nacos支持加权路由,使您更容易在数据中心的生产环境中实现中间层负载平衡、灵活的路由策略、流量控制和简单的DNS解析服务。它可以帮助您轻松实现基于dns的服务发现,并防止应用程序耦合到特定于供应商的服务发现api。

4. 服务和元数据管理: Nacos提供了一个易于使用的服务仪表板,帮助您管理服务元数据、配置、kubernetes DNS、服务运行状况和度量统计数据。

Nacos 优势

  • 易⽤:简单的数据模型,标准的restfulAPI,易用的控制台,丰富的使用文档。
  • 稳定:99.9% 高可用,脱胎于历经阿里巴巴10 年生产验证的内部产品,支持具有数百万服务的大规模场景,具备企业级SLA 的开源产品。
  • 实时:数据变更毫秒级推送生效;1w 级,SLA 承诺1w 实例上下线1s,99.9% 推送完成;10w级,SLA 承诺1w 实例上下线3s,99.9% 推送完成;100w 级别,SLA 承诺1w 实例上下线9s 99.9% 推送完成。
  • 规模:十万级服务/配置,百万级连接,具备强大扩展性。

Nacos 入门

Nacos 下载

Nacos下载地址:https://github.com/alibaba/nacos/releases ;目前最新版本为2.3.0的beta公测版本,我们可以下载合适的版本使用,建议使用2.x版本。Windows版本下载zip包,Linux版本下载tar.gz包。
在这里插入图片描述

Nacos 安装

在linux的nacos安装目录执行tar -zxvf nacos-server-2.1.1.tar.gz解压安装包,解压后的目录为。

alt
目录结构介绍:

bin:启动脚本目录,startup.sh 用于启动服务,shutdown.sh用于停止服务
conf:配置文件目录,application.properties核心配置文件,nacos-mysql.sql用mysql做数据源所需的sql文件。

注意:nacos服务本身就是一个Java应用,所以需要JDK环境才能运行,官方建议最好是JDK8以及更高的版本。

nacos服务启动需要在bin目录下执行./startup.sh -m standalone命令和参数,不加参数默认会以集群模式启动。通过查看nacos目录下的logs/start.out文件可以了解项目启动情况和端口号。
alt
在浏览器输入主机ip:8848/nacos访问Nacos控制台,默认用户名和密码都是nacos/nacos

nacos-console

Nacos 注册中心

Open API实现注册

Nacos提供了一系列的Open API接口来帮助我们快速的操作Nacos,所以我们可以通过调用Open API的http接口来简单地进行的服务注册。

请求方式:POST

注册实例的接口:http://127.0.0.1:8848/nacos/v2/ns/instance

必填参数: serviceName, ip, port, ephemeral, metadata

ephemeral=true时调用接口注册的是临时实例,临时实例需要自己上报心跳给Nacos Server,由于是通过接口注册的,客户端无法进行心跳上报,所以等待15秒实例会变为不健康,等待30秒后实例会被删除。
在这里插入图片描述
在这里插入图片描述

Java SDK实现注册

我们可以使用Nacos提供的Java SDK原生API,来实现手动注册服务到Nacos的功能,这种方式比较直接,也便于我们了解Nacos注册的底层原理。

引入Nacos的Java SDK

 <dependency>
     <groupId>com.alibaba.nacos</groupId>
     <artifactId>nacos-client</artifactId>
     <version>2.1.1</version>
 </dependency>

Nacos需保证有权限才可以注册,应该在application.properties配置文件中开启认证功能。

nacos.core.auth.enabled = true

Java代码实现简单的服务注册功能

 public static void main(String[] args) throws NacosException,  InterruptedException {

     Properties properties = new Properties();
     properties.setProperty("server-addr","127.0.0.1:8848");
     properties.setProperty("serverAddr","127.0.0.1:8848");
     properties.setProperty("username","nacos");
     properties.setProperty("password","nacos");
     NamingService namingService = NamingFactory.createNamingService(properties);
     namingService.registerInstance("app","192.168.8.130",9000);
     TimeUnit.SECONDS.sleep(60);
  }

程序运行后查看Nacos控制台的服务管理/服务列表,可以看到服务被成功注册到了Nacos上,默认是注册到public命名空间的default_group默认分组下。

alt
当程序运行结束后,服务列表上的服务实例信息也随之删除,因为Nacos默认注册的实例都是临时实例。注册时也可以按照需求设置服务是临时实例还是持久化实例,持久化实例会保留不健康的服务实例信息。

注册持久化实例

 public static void main(String[] args) throws NacosException,  InterruptedException {

      Properties properties = new Properties();
      properties.setProperty("server-addr","127.0.0.1:8848");
      properties.setProperty("serverAddr","127.0.0.1:8848");
      properties.setProperty("username","nacos");
      properties.setProperty("password","nacos");
      NamingService namingService = NamingFactory.createNamingService(properties);

      Instance instance = new Instance();
      instance.setIp("192.168.8.129");
      instance.setPort(9001);
      instance.setEphemeral(false);    // 设置实例为持久化实例
      namingService.registerInstance("app1",instance);
      TimeUnit.SECONDS.sleep(60);
  }

运行程序查看持久化实例注册成功,实例是健康的;当60s过后程序结束,健康实例数变为0,而实例数还是1,此时服务实例信息已经被持久化了。实例是否健康是通过Nacos的健康检查机制检测出来的,临时实例会采用客户端服务定时心跳上报的方式检查,而持久化实例采用的是注册中心主动探测机制。

alt
alt
Nacos集群是同时支持APCP模式。当注册的实例是临时实例时,使用的是AP模式,在AP模式下,Nacos会使用Distro协议来维护集群结点的数据同步问题,会优先保证集群的高可用。当注册的实例是持久化实例时,会使用CP模式的Raft协议来保证集群结点数据的强一致性,对数据的一致性比较看重。

SpringBoot实现注册

Nacos2.x版本使用了httpgrpc两种方式来进行服务的通信和注册。当注册的服务是临时实例时,会使用grpc框架进行通信注册,通过建立长连接来和服务端维持心跳;如果注册的服务是持久化实例时,则会调用Open API的http接口对服务进行注册。Springboot项目在启动时会自动地注册到Nacos上,底层是通过Spring的事件监听机制完成的。

在父工程引入项目依赖

<dependencyManagement>
       <dependencies>
           <!-- springboot 2.3.12.RELEASE -->
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-dependencies</artifactId>
               <version>2.3.12.RELEASE</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
           <!-- springcloud Hoxton.SR12 -->
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-dependencies</artifactId>
               <version>Hoxton.SR12</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
           <!-- springcloud alibaba 2.2.8.RELEASE -->
           <dependency>
               <groupId>com.alibaba.cloud</groupId>
               <artifactId>spring-cloud-alibaba-dependencies</artifactId>
               <version>2.2.8.RELEASE</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
</dependencyManagement>

在父工程下新建子模块 nacos-client-provider,引入核心依赖。

  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      <exclusions>
          <exclusion>
               <groupId>com.alibaba.nacos</groupId>
               <artifactId>nacos-client</artifactId>
          </exclusion>
     </exclusions>
  </dependency>
  <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>2.1.1</version>
  </dependency>

application.yml文件配置服务注册信息。

server:
  port: 9998
spring:
  application:
    name: nacos-client-provider  # 注册的服务名
  cloud:
    nacos:       # 注册中心和配置中心是同一个时的写法
      username: nacos  
      password: nacos
      server-addr: localhost:8848  

启动 nacos-client-provider 服务,发现服务被自动注册到Nacos上了。
在这里插入图片描述
SpringBoot实现自动注册的原理是使用了Spring中的事件监听机制。SpringBoot的微服务项目在启动时会发布一个ServletWebServerInitializedEvent事件,该事件会被AbstractAutoServiceRegistration类的onApplicationEvent(WebServerInitializedEvent event)方法监听到,监听方法在执行过程中会调用Nacos的NacosAutoServiceRegistration类重写过的register()方法,最后调用NacosServiceRegistry真正执行注册的register(Registration registration)方法完成注册。

alt

Nacos不同版本的注册方式

  • Nacos1.x版本的服务注册方式都是使用的http接口,在该版本中的SDK方式注册底层也是直接调用Open API的http接口进行注册。
  • Nacos2.x版本除了支持Open API的http接口注册,还新增加了grpc的方式进行注册,在新版本中使用SDK方式注册时,对于持久实例的注册还是使用的http接口方式,而对于临时实例的注册则会采用RPC与注册中心保持长连接,客户端会定时的通过RPC连接向Nacos 注册中心发送心跳,保持连接的存活。如果客户端和注册中心的连接断开,那么注册中心会主动剔除该 client 所注册的服务,以达到下线的效果。

Nacos 配置中心

背景

在单体架构的时候我们可以将配置写在配置文件中,但有⼀个缺点就是每次修改配置都需要重启服务才能生效。
当应用程序实例比较少的时候还可以维护。如果转向微服务架构有成百上千个实例,每修改⼀次配置要将全部实例重启,不仅增加了系统的不稳定性,也提高了维护的成本。

对于以上的问题,Nacos为我们提供了一个功能强大的配置中心。Nacos的配置中心具有:便于快速动态修改配置的界面、服务配置的热更新(无需重启服务)、服务配置的历史版本追踪(30天内)、服务配置的多级权限隔离等特性。

权限控制

进入权限控制/用户列表控制台界面,添加mj_dev/123mj_tes/123mj_prod/123 这三个用户账号和密码。

alt
进入权限控制/角色管理控制台界面,为这三个用户绑定三个角色ROLE_DEVROLE_TESTROLE_PROD

alt
进入 命名空间 控制台界面,创建三个命名空间用于环境隔离 devtest prod

在这里插入图片描述
最后在权限控制/权限管理控制台界面,为这三个角色分别绑定命名空间 devtest prod以及读写 (rw)权限,这样就做到了账号和命名空间的访问权限控制。

在这里插入图片描述

SpringCloud读取配置

新建nacos-client-goods工程,引入核心依赖。

 <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 </dependency>

新建bootstrap.yml配置文件,引入配置中心后需要将配置中心信息写在此文件中,否则配置中心无法连接。

spring:
  application:
    name: goods-service        # 服务名称
  profiles:
    active: dev                # 激活的配置文件
  cloud:
    nacos:
      server-addr: localhost:8848     # 注册中心地址
      username: mj_dev                # 开发环境账号
      password: 123                   # 开发环境密码
      discovery:
        namespace: b8aac48d-d92a-4234-ab42-754bcf37fd5e    # 命名空间为开发环境
        group: DEV_GROUP                                   # 服务所在的分组
        cluster-name: HZ                                   # 服务所在的集群
      config:
        namespace: b8aac48d-d92a-4234-ab42-754bcf37fd5e         # 命名空间,用于环境隔离
        group: DEV_GROUP                                        # 配置文件的分组,用于配置隔离
        file-extension: yaml                                    # 配置文件后缀格式

配置管理/配置列表 控制台界面,新建 goods-service.yamlgoods-service-dev.yaml 配置文件。Nacos对Springboot的配置文件也只支持 yamlproperties这两种格式。

配置文件的命名规则有:

  1. {spring.application.name}.yaml
  2. {spring.application.name}.properties
  3. {spring.application.name}-{spring.profiles.active}.yaml
  4. {spring.application.name}-{spring.profiles.active}.properties
    在这里插入图片描述
    在这里插入图片描述

测试使用@Value()注解读取配置的值,使用@RefreshScope注解开启配置变更的自动刷新机制,输出的日期格式为:yyyy/MM/dd HH:mm:ss,证明 {spring.application.name}-{spring.profiles.active}.yaml 配置的优先级高于{spring.application.name}.yaml

@RestController
@RefreshScope
public class ConfigCenterController {

    @Value("${global.date.format}")
    private String dateFormat;
    
    @GetMapping("/now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateFormat));
    }
 }   

共享和扩展配置

在日常开发中我们可能会有很多公用的配置,比如多个微服务使用的是同一个数据库或者Redis的情况,这时就可以用到共享配置(shared-configs)。共享配置通过对可重用配置的抽取,在多个应用中引入来实现配置的共享。

在Nacos上新建common-env.properties的共享配置文件,用来设置在各个应用中都通用的共享变量。
在这里插入图片描述
bootstrap.yml文件中配置共享配置的dataIdgrouprefresh属性值,多个共享配置时通过shared-configs[n]配置优先级,n 越大优先级越高。

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848     # 配置中心地址
        username: mj_dev                # 开发环境账号
        password: 123                   # 开发环境密码
        namespace: b8aac48d-d92a-4234-ab42-754bcf37fd5e         # 命名空间,用于环境隔离
        group: DEV_GROUP                                        # 配置文件的分组,用于配置隔离
        file-extension: yaml                                    # 配置文件后缀格式
        shared-configs[0]:                      # shared-configs[n],n 越大优先级越高
            data-id: common-env.properties      # 设置dataId,即文件名
            group: DEFAULT_GROUP                # 设置文件所在的分组,不设置也是默认分组
            refresh: true                       # 配置变更会自动刷新给服务

使用@ConfigurationProperties()注解自动装配共享配置的属性值,这些属性在所有应用中都是通用的,所以标识为共享配置,其实shared-configs也只是一种标识,并不是只有这样配置后才能共享。

@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix = "money.unit")
public class MoneyUnitConfig {
    private String china;
    private String america;
    private String britain;
}

另外一个扩展配置(extension-configs)的用法是,对共享配置进行修改和扩展,因为扩展配置的优先级高于共享配置,所以可以按照应用的需求对公共配置的属性进行修改和扩充。

在Nacos上新建extension-env.properties的配置文件,用来修改和扩展共享配置的属性值。
在这里插入图片描述
bootstrap.yml文件中设置扩展配置的dataIdgrouprefresh属性值。

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848     # 配置中心地址
        username: mj_dev                # 开发环境账号
        password: 123                   # 开发环境密码
        namespace: b8aac48d-d92a-4234-ab42-754bcf37fd5e         # 命名空间,用于环境隔离
        group: DEV_GROUP                                        # 配置文件的分组,用于配置隔离
        file-extension: yaml                                    # 配置文件后缀格式
        shared-configs:                         # 共享配置
          - data-id: common-env.properties      # 设置dataId,即文件名
            group: DEFAULT_GROUP                # 设置文件所在的分组,不设置也是默认分组
            refresh: true                       # 配置变更会自动刷新给服务
        extension-configs:                      # 扩展配置
          - data-id: extension-env.properties
            refresh: true    

测试扩展配置(extension-configs)的优先级是否真的大于共享配置(shared-configs)。修改MoneyUnitConfig类,输出对象属性自动装配的值,通过输出结果证明:扩展配置优先级大于共享配置,而且可以对共享配置做修改和补充。

@Setter
@Getter
@ToString
@Configuration
@ConfigurationProperties(prefix = "money.unit")
public class MoneyUnitConfig implements InitializingBean {

    private String china;
    private String chinaStandard;
    private String america;
    private String britain;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("输出结果:china = "+china+" ,chinaStandard = "
                +chinaStandard+" ,america = "+america+" ,britain = "+britain);
    }
}

输出结果:china =,chinaStandard = 人民币 ,america = 美元 ,britain = 英镑

多环境配置支持

Nacos的注册中心和配置中心是可以分开部署的,所以我们也可以把Nacos的配置中心和注册中心的配置分开,万一以后有了更优秀的注册中心产品,我们也可以灵活切换。

bootstrap.yml配置文件进行修改,增加多环境支持。

spring:
  application:
    name: goods-service
  profiles:
    active: dev     # 激活不同环境的配置
---
spring:
  profiles: dev      # 开发环境的nacos配置中心信息
  cloud:
    nacos:
      config:
        server-addr: localhost:8848     # 注册中心地址
        username: mj_dev                # 开发环境账号
        password: 123                   # 开发环境密码
        namespace: b8aac48d-d92a-4234-ab42-754bcf37fd5e         # 命名空间,用于环境隔离
        group: DEV_GROUP                                        # 配置文件的分组,用于配置隔离
        file-extension: yaml                                    # 配置文件后缀格式
---
spring:
  profiles: test        # 测试环境的nacos配置中心信息
  cloud:
    nacos:
      config:
        server-addr: localhost:8848      # 注册中心地址
        username: mj_test                # 测试环境账号
        password: 123                    # 测试环境密码
        namespace: 11c2dc6c-f1c9-4b44-927f-d1cb6f7e3202      # 命名空间,用于环境隔离
        group: TEST_GROUP                                    # 配置文件的分组,用于配置隔离
        file-extension: yaml                                 # 配置文件后缀格式
---
spring:
  profiles: prod      # 生产环境的nacos配置中心信息
  cloud:
    nacos:
      config:
        server-addr: localhost:8848      # 注册中心地址
        username: mj_prod                # 生产环境账号
        password: 123                    # 生产环境密码
        namespace: 90ec3dd0-ee97-4a5b-a048-8054fad3b62b         # 命名空间,用于环境隔离
        group: PROD_GROUP                                       # 配置文件的分组,用于配置隔离
        file-extension: yaml                                    # 配置文件后缀格式

开发环境的配置,修改Nacos上的goods-service-dev.yaml配置文件,添加注册中心的自动配置属性。为了防止网络故障读取不到配置,在应用本地的application-dev.yml配置文件也需要配置注册中心的自动配置属性。

alt
测试环境的配置,修改Nacos上的配置文件goods-service-test.yaml,添加注册中心的自动配置属性。同样在应用本地的application-test.yml配置文件也需要配置注册中心的自动配置属性,但是由于Nacos上的配置优先级更高,所以会以goods-service-test.yaml为主。

alt
生产环境的配置,相同的操作,在goods-service-test.yaml配置文件中添加Nacos注册中心的自动配置属性,在应用本地的application-test.yml配置文件也添加同样的配置。

alt

到这里项目已经完成了多环境配置的搭建,就只需要通过简单的配置spring.profiles.active属性的值就可以切换到不同的环境上。当切换在开发环境启动时,服务会被注册到开发环境,也会只读取开发环境的配置,这样就做到了不同开发人员之间的环境和配置的隔离。

在这里插入图片描述
在这里插入图片描述

Nacos 健康检查机制

什么是健康检查机制

健康检查是注册中心的基本功能之一,这是因为注册中心不应该仅仅提供服务注册和发现功能,还应该保证对服务的可用性进行监测,对不健康或不可用的服务应该进行标识或剔除,维护实例的生命周期,以保证客户端尽可能的查询到可用的服务列表。

注册中心的健康检查机制

注册中心的产品有很多,比如Nacos、Eureka、Zookeeper等,他们都实现了自己的健康检查机制。健康检查机制主要有两种:第⼀种方式是客户端定时主动上报心跳,告诉服务端自己的健康状态,如果在规定的时间没有上报,那么服务端就判定服务实例已经不健康;第二种则是服务端主动向客户端进行探测,检查客户端是否还健康。

alt
目前主流的注册中心,对于健康检查机制主要都采用了TTL(Time To Live)机制,即客户端在⼀定时间没有向注册中心发送心跳,那么注册中心会认为此服务不健康,进而触发后续的剔除逻辑。Nacos和Eureka使用的就是客户端定时主动上报心跳这个方式,不过Nacos还支持服务端主动向客户端进行探测的方式。对于主动探测的方式,根据不同的场景,需要采用的方式可能会有不同。

Nacos 的两种健康检查机制

我们知道Nacos 的服务实例可以分为临时实例和持久化实例,这两种实例采用的健康检查机制是不同的。

临时实例健康检查机制:

临时实例采用的是客户端定时主动上报心跳的方式,默认客户端服务会以5秒为周期向Nacos服务端发送心跳包,如果心跳包的间隔时间超过了15秒,那么服务端会将此服务实例标记为不健康实例,如果心跳包的间隔时间超过了30秒,那么服务实例将会被删除。

可以修改默认的客户端心跳配置时间

# 心跳上报的周期时间(ms)
spring.cloud.nacos.discovery.metadata.preserved.heart.beat.interval = 5000
# 心跳超时被标记为不健康实例的时间
spring.cloud.nacos.discovery.metadata.preserved.heart.beat.timeout= 10000
# 实例心跳超时被删除的时间
spring.cloud.nacos.discovery.metadata.ip.delete.timeout= 15000

配置生效后可以在服务实例的元数据中看到,也可以直接编辑修改心跳配置。
在这里插入图片描述

持久化实例健康检查机制:

对于持久化实例的健康检查,Nacos 采用的是注册中心探测机制,注册中心会在持久化服务初始化时根据客户端选择的协议类型注册探活的定时任务。Nacos现在内置提供了三种探测的协议,即Http、TCP 以及MySQL。⼀般而言Http 和TCP 已经可以涵盖绝大多数的健康检查场景,而MySQL 主要用于特殊的业务场景。

持久化实例为什么会采用Nacos服务端主动探测机制呢?

首先我们要知道,持久化实例是Nacos1.0.0增加的新特性,他对应的是一些通过Open API注册的持久化服务,Nacos 中使用SDK 对于持久化实例的注册实际也是使用Open API 的方式进行注册。这些服务在第一次注册成功就会被持久化存储下来,他们可能并不知道注册中心存在,因为他们可以被任何人调用接口注册,比如我调用接口注册了一个Redis服务,这时Redis服务是无法给Nacos发送心跳的,因为Redis服务压根不知道注册中心的存在,也没有实现给Nacos主动上报心跳的功能,所以持久化实例需要Nacos主动去探测服务的健康状态。

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

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

相关文章

ThinkPad产品如何升级BIOS程序

操作步骤: 重要提示&#xff1a; 更新BIOS存在风险&#xff01;如果您的电脑在此过程中出现死机&#xff0c;系统崩溃或断电&#xff0c;则BIOS或UEFI固件程序可能会损坏&#xff0c;这将使您的电脑无法启动。 由于BIOS的版本或者在升级过程中出错&#xff0c;可能会造成不可…

009、引用

1. 引用与借用 下面的示例重新定义了一个新的 calculate_length 函数。与之前不同的是&#xff0c;新的函数签名使用了 String 的引用作为参数而没有直接转移值的所有权&#xff1a; fn main() { let s1 String::from("hello"); let len calculate_length(&s1…

气象预报与计算机技术:深度融合与未来展望

气象预报与计算机技术:深度融合与未来展望 一、引言 气象预报,作为人类对自然界气象变化的探索与预测,随着时间的推移和技术的进步,已经逐渐从单纯的经验模式转变为依赖于精密的仪器与强大的计算机技术的科学预测。在本文中,我们将深入探讨气象预报与计算机技术之间的密…

[2024区块链开发入门指引] - 比特币与区块链诞生

一份为小白用户准备的免费区块链基础教程 工欲善其事,必先利其器 Web3开发中&#xff0c;各种工具、教程、社区、语言框架.。。。 种类繁多&#xff0c;是否有一个包罗万象的工具专注与Web3开发和相关资讯能毕其功于一役&#xff1f; 参见另一篇博文&#x1f449; 2024最全面…

数据结构:堆的三部曲 (一)堆的实现

堆的实现 1.堆的结构1.1堆的定义理解 2.堆的实现&#xff08;以小根堆为例&#xff09;2.1 堆结构体的定义2.2 堆的插入交换函数向上调整算法插入函数的代码 2.3 堆的删除向下调整算法&#xff1a;删除函数的代码&#xff1a; 2.4其他操作 3.测试以及完整源代码实现3.1测试代码…

山西电力市场日前价格预测【2024-01-02】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-02&#xff09;山西电力市场全天平均日前电价为92.93元/MWh。其中&#xff0c;最高日前电价为275.90元/MWh&#xff0c;预计出现在18:00。最低日前电价为0.00元/MWh&#xff0c;预计出现…

【数据结构与算法】第1章绪论(头歌习题)【合集】

文章目录 第1关&#xff1a;求和任务描述编程要求代码 第2关&#xff1a;求倒数和的倒数任务描述编程要求完整代码 第3关&#xff1a;回文数任务描述编程要求完整代码 第4关&#xff1a;求素数个数任务描述编程要求完整代码 第5关&#xff1a;最大因子任务描述编程要求完整代码…

第6课 用window API捕获麦克风数据并加入队列备用

今天是2024年1月1日&#xff0c;新年的第一缕阳光已经普照大地&#xff0c;祝愿看到这篇文章的所有程序员或程序爱好者都能在新的一年里持之以恒&#xff0c;事业有成。 今天也是我加入CSDN的第4100天&#xff0c;但回过头看一看&#xff0c;这么长的时间也没有在CSDN写下几篇…

2023-刻苦自励,2024-奋起直追!

点击上方“嵌入式应用研究院”&#xff0c;选择“置顶/星标公众号” 干货福利&#xff0c;第一时间送达&#xff01; 来源 | 嵌入式应用研究院 整理&排版 | 嵌入式应用研究院 一、引言 时光如影&#xff0c;岁月如梭。转眼之间&#xff0c;2023年已经过去&#xff0c;在这一…

拒绝采样(算法)总结

先说说什么是拒绝采样算法&#xff1a;就类似于数学上的求阴影面积的方法&#xff0c;直接求求不出来&#xff0c;就用大面积 - 小面积 阴影面积的办法。 所谓拒绝 和 采样 &#xff1a;就像是撒豆子计个数&#xff0c;计算概率问题一样&#xff0c;大桶里面套小桶&#xff0c…

[C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计

源码地址&#xff1a; github地址&#xff1a;https://github.com/Ahmednull/L2CS-Net L2CS-Net介绍&#xff1a; 眼睛注视&#xff08;eye gaze&#xff09; 是在各种应用中使用的基本线索之一。 它表示用户在人机交互和开放对话系统中的参与程度。此外&#xff0c;它还被用…

Docker 从入门到实践:Docker介绍

前言 在当今的软件开发和部署领域&#xff0c;Docker已经成为了一个不可或缺的工具。Docker以其轻量级、可移植性和标准化等特点&#xff0c;使得应用程序的部署和管理变得前所未有的简单。无论您是一名开发者、系统管理员&#xff0c;还是IT架构师&#xff0c;理解并掌握Dock…

【数据结构】栈和队列(队列的基本操作和基础知识)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​ 目录 前言 队列 队列的概念和结构 队列的…

域名转移:将腾讯云转移至阿里云

当时注册域名时&#xff0c;腾讯域云相对便宜&#xff0c;但目前阿里云在业界更加成熟&#xff0c;因此将自己申请的域名由阿里云转移至阿里云&#xff0c;并记录转移过程。 一、域名转出 进入腾讯云&#xff0c;登陆后选择控制台&#xff0c;选择我的资源–域名注册–全部域名…

【华为机试】2023年真题B卷(python)-滑动窗口最大值

一、题目 题目描述&#xff1a; 有一个N个整数的数组&#xff0c;和一个长度为M的窗口&#xff0c;窗口从数组内的第一个数开始滑动直到窗口不能滑动为止&#xff0c; 每次窗口滑动产生一个窗口和&#xff08;窗口内所有数的和&#xff09;&#xff0c;求窗口滑动产生的所有窗口…

LTPI协议的理解——1、LTPI协议的定义和结构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 LTPI协议的理解——1、LTPI协议的定义和结构 定义DC-SCM 2.0 LTPI 结构GPIO通道I2C/SMBus通道Uart通道OEM通道数据通道 总结 定义 LTPI (LVDS Tunneling Protocol & Int…

单片机数据发送程序

#include<reg51.h> //包含单片机寄存器的头文件 /***************************************************** 函数功能&#xff1a;向PC发送一个字节数据 ***************************************************/ void Send(unsigned char dat) { SBUFdat; whil…

【ESP-NOW with ESP32:从多个开发板接收数据(多对一)】

【ESP-NOW with ESP32&#xff1a;从多个开发板接收数据&#xff08;多对一&#xff09;】 1. 项目概况2. 先决条件2.1 环境配置2.2 所需零件 3. 获取接收板 MAC 地址4. ESP32 发送码 &#xff08;ESP-NOW&#xff09;4.1 代码的工作原理4.2 setup&#xff08;&#xff09;4.3 …

异步处理方案

目录 1.通过promise的链式调用将异步方法变为同步执行 2.使用async及await 3.回调函数方式 4.三种方式对比 5.async及await使用的注意点 1.通过promise的链式调用将异步方法变为同步执行 function get1(){return new Promise((resolve,reject) >{console.log(执行get1接…

B端产品学习-市场调研与分析

B端产品市场调研与分析 目录&#xff1a; 为什么要做产品调研 B端产品调研对比C端产品调研 B端产品调研要怎么做 为什么要做产品调研 杰克特劳特说过&#xff1a;“成为唯一。如果不能争得第一&#xff0c;那就找到一个能够成为第一的细分&#xff0c;这就是定位的第一法则…