3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)

3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)

文章目录

  • 3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)
  • 前言
  • 1. Spring Cloud Eureka 的概述
    • 1.1 服务治理概述
    • 1.2 服务注册与发现
  • 2. 实践:创建单机 Eureka Server 注册中心
    • 2.1 需求说明 + 图解
    • 2.3 具体实现步骤
      • 2.3.1 创建相关的 Moduel 以及 完成配置
      • 2.3.2 配置 member-service-consumer-80 作为 EurekaClient 可 以 拉 取/获取 e-commerce-eureka-server-9001 提供的服务信息
      • 2.3.3 架构示意图
      • 2.3.4 将 member-service-provider-10000 作为 EurekaClient 注册到 e-commerce-eureka-server-9001 成为服务提供者
      • 2.3.5 架构示意图
  • 3. Service Consumer 、Service Provider 、EurekaServer 的维护机制
  • 4. Eureka 自我保护模式
    • 4.1 自我保护模式理论
    • 4.2 禁用自我保护模式(生产环境中, 一般不禁用)
  • 5. 搭建 EurekaServer 集群- 实现负载均衡故障容错
    • 5.1 为什么需要集群 Eureka Server
    • 5.2 需求分析/图解
    • 5.3 搭建 Eureka Server 集群
  • 6. 补充:定义本地的域名机制
    • 5.4 搭建会员中心服务提供方-集群
    • 5.5 配置服务消费端 member-service-consumer-80 使用会员中心服务集群
    • 5.6 获取 Eureka Server 服务注册信息 - DiscoveryClient
      • 5.5.1 具体操作步骤:
        • 5.5.1.1 注意事项和细节说明
  • 7. Eureka 后续说明
  • 8. 总结:
  • 9. 最后:


前言

  • 对应上一篇学习内容:🌟🌟🌟2. Spring Cloud 微服务基础环境搭建_搭建cloud微服务-CSDN博客
  • 对应下一篇学习内容:🌟🌟🌟 4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明-CSDN博客

1. Spring Cloud Eureka 的概述

从上个学习内容上我们可以知道 补充, 当中的 、Spring Cloud 组件选型- 图

在这里插入图片描述

从上图可以看出,目前主流的服务注册/发现的组件是 Nacos,但是Eureka 作为一个老牌经典的服务
注册/发现技术还是有必要回顾一下:
原因:

  • 一些早期的分布式 微服务项目使用的是 Eureka ,大家工作中,完全有可能遇到这种情况。
  • 后期的服务注册/发现组件/技术,都参考了 Eureka 的设计和理念,学习了 Eureka 后,我们上手
    Nacos 容易很多,而且理解的更深刻。

分析上述我们上一篇内容补充 当中项目架构问题分析

在这里插入图片描述

当前项目问题分析:

  1. 在企业项目中,服务消费访问请求会存在高并发
  2. 如果只有一个会议中心-提供服务,可用性就比较差了
  3. 所以,会议中心提供服务往往是一个集群,也就是说会有多个会议中心-提供服务微服务模块
  4. 那么这个时候,就存在一个问题就是服务消费方,怎么去发现可以使用的服务(哪些服务又不可以使用)
  5. 当服务消费方,发现了可以使用的服务后(可能是多个,又存在一个问题就是到底调用 A服务,
    还是调用B服务,这就引出了服务注册和负载均衡的问题)
  6. Eureka 就可以解决上述问题

引入 Eureka 项目架构,一图胜千言

在这里插入图片描述

上图 Eureka 项目架构图解析:

  1. 会员中心——> 提供服务的,在项目中,会做成集群 ,提供高可用
  2. Eureka Server 有必要的话,也可以做成集群
  3. Eureka 包含两个组件: Eureka ServerEureka Client
  4. Eureka Server 提供注册服务,各个微服务节点童工配置启动后,会在 EurekaServer 中进行注册,
    这样Eureka Server 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
  5. Eureka Client 通过注册中心进行访问,是一个Java客户端,用于简化 Eureka Server 的交互,
    客户端同时也具备一个内置的,使用轮询(round-robin) 负载算法的负载均衡器。在应用启动后,
    将会向 Eureka Server 发送心跳(默认周期为 30秒)。如果 Eureka Server 在多个心跳周期
    内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)

1.1 服务治理概述

Eureka 实现服务治理

在传统的 rpc 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理困难,所以 需要治理服务之间依赖关系

服务治理实现服务调用、负载均衡、容错等,实现服务发现与注册。

二说分布式开发: https://jingyan.baidu.com/article/46650658def479f549e5f83e.html

1.2 服务注册与发现

在这里插入图片描述

  • Eureka 采用了CS[client-server-java] 基础我们讲过一个多人聊天项目。的设计架构,
    Eureka Server 作为服务注册的服务器,它是服务注册中心

  • 系统中的其它微服务,使用Eureka 的客户端连接到 Eureka Server 并维持心跳连接,
    通过 Eureka Server 来监控系统中各个微服务是否正常运行

  • 在服务注册与发现中,有一个注册中心,当服务启动的时候,会把当前自己服务器的信息,比如服务地址通讯地址等以别名方式注册到注册中心上。

  • 服务消费者或者服务提供者,以服务别名的方式去注册中心上获取到实际的服务提供
    者通讯地址,然后,通过 RPC 调用服务

2. 实践:创建单机 Eureka Server 注册中心

2.1 需求说明 + 图解

在这里插入图片描述

2.3 具体实现步骤

2.3.1 创建相关的 Moduel 以及 完成配置

  1. 创建 e-commerce-eureka-server-9001 微服务模块[作为注册中心]

在这里插入图片描述

在这里插入图片描述

父工程的 pom.xml-会做相应变化,管理 e-commerce-eureka-server-9001 微服务子模块

在这里插入图片描述

  1. 修改 e-commerce-eureka-server-9001 的 pom.xml , 加入依赖
    在这里插入图片描述
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>e-commerce-center</artifactId><groupId>com.rainbowsea</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>e-commerce-eureka-server-9001</artifactId><dependencies><!--        引入web-starter 说明:这里我们使用版本仲裁(从父项目继承了版本)--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--1. starter-actuator 是sprng boot 程序的监控系统,可以实现健康检查,info 信息等2. 访问http://localhost:10000/actuator 可以看到相关链接,还可以做相关配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- 引入 eureka-server 场景启动器 starter: 使用版本仲裁注意:不要搞错了,有一个 starter 的--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!--        lombok 引入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><!--            不进行转递依赖--><optional>true</optional></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency><!--        引入 test-starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        引入我们自己对 bean 封装成 api 的模块内容--><dependency><groupId>com.rainbowsea</groupId><artifactId>e_commerce_center-common-api</artifactId><version>${project.version}</version></dependency></dependencies></project>
  1. 创建 resources/application.yml

在这里插入图片描述

server:port: 9001
# 配置 eureka-server
eureka:instance:hostname: localhost # 服务实例名或者别名client:# 配置不向注册中心注册自己,默认是 trueregister-with-eureka: false# 表示自己就是注册中心,作用就是维护注册服务实例,不需要去检索服务,默认是 truefetch-registry: falseservice-url:#设置与 eureka server 交互的模块,查询服务和注册服务都需要依赖这个地址#      defaultZone: http://localhost:9001/eureka/ ,也可以使用别名,在同一个文件当中可以引用defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

特别说明:注意:这里从架构图上可以知道的是,这里的这个e-commerce-eureka-server-9001 充当为 Eureka Server 服务角色 ,所以自然,我们需要将其配置为 服务角色。

在这里插入图片描述

  1. 创建主启动类 com/rainbwosea/springcloud/EurekaApplication.java
    在这里插入图片描述
package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer // @EnableEurekaServer 表示该项目/该模块/该程序作为 Eureka Server 角色进行运行
@SpringBootApplication
public class EurekaApplication9001 {public static void main(String[] args) {SpringApplication.run(EurekaApplication9001.class, args);}
}
  1. 完成测试:

在这里插入图片描述

补充说明: Spring Eureka 完整的可视化页面展示

在这里插入图片描述

2.3.2 配置 member-service-consumer-80 作为 EurekaClient 可 以 拉 取/获取 e-commerce-eureka-server-9001 提供的服务信息

2.3.3 架构示意图

在这里插入图片描述

配置 member-serivce-consumer-10000 作为 EurekaClient 注册发现到 commerce-eureka-server-9001 服务当中,我们需要在 resource目录下的 application.yaml 文件当进行一个配置。如下图所示:

  1. 配置 member-serivce-consumer-80 作为 EurekaClient 注册发现到 commerce-eureka-server-9001 服务当中,我们需要在 resource目录下的 application.yaml 文件当进行一个配置。如下图所示:

在这里插入图片描述

server:port: 80 # 浏览器默认就是 80 端口spring:application:name: member-service-consumer-80 # 该项目/模块名称eureka:client:register-with-eureka: true # 表示将自己注册到 Eureka-Server 当中fetch-registry: true # 表示将信息发送到 Eureka-Server 当中service-url:# 表示将自己注册到那个 eureka-serverdefaultZone: http://localhost:9001/eureka

在这里插入图片描述

  1. 同时我们也需要将该 member-service-consumer-80项目,配置指明为是 Eureka Client 角色,在该项目的场景启动器上添加 注解即可

在这里插入图片描述

package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;// 如果错误: 加入排除 DataSourceAutoConfiguration 自动配置 
//@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient //表示将项目/模块/程序 标注作为 Eureka Client
@SpringBootApplication
public class MemberConsumerApplication80 {public static void main(String[] args) {SpringApplication.run(MemberConsumerApplication80.class, args);}
}

运行测试:

注意:测试的时候,我们尽量先将 EukekatServer (也就是我们这里的 e-commerce-eureka-server-9001) 注册中心启动,然后再将 Eukekat Client(也就是我们这里的 member-service-consumer-80) 启动。

然后,打开浏览器输入:http://localhost:9001/ 查看结果。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.3.4 将 member-service-provider-10000 作为 EurekaClient 注册到 e-commerce-eureka-server-9001 成为服务提供者

上述操作我们是已经将 定义为了一个 Eureka Server 服务器,那么我们就需要将 服务提供者 注册到我们的 Eureka Server 当中。注册到 Eureka Server 当中,换句话说:就是将我们 Eureka Client 告诉 Eureka Server 我还没有宕机,还活着,我还可以继续提供服务下去。

2.3.5 架构示意图

在这里插入图片描述

配置 member-service-provider-10000 作为 EurekaClient 注册发现到 commerce-eureka-server-9001 服务当中,我们需要在 resource目录下的 application.yaml 文件当进行一个配置。如下图所示:

在这里插入图片描述

server:port: 10000
spring:application:name: member-service-provider-10000 # 配置应用的名称datasource:type: com.alibaba.druid.pool.DruidDataSource # 配置 alibaba 的数据库连接池password: MySQL123username: rooturl: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8
mybatis:mapper-locations: classpath:mapper/*.xml # 指定 mapper.xml 文件位置 classpath 表示 resources 目录下type-aliases-package: com.rainbowsea.springcloud.entity # 实例 bean 类所在的包,这样可以通过类名的方式# 配置 eureka-client
eureka:client:register-with-eureka: true # 表示将自己注册到 Eureka-Server# 表示从 Eureka-Server 抓取注册信息# 如果是单节点,是可以配置的,但是如果是一个集群,则必须配置true# 才能配合 Ribbon 使用负载均衡fetch-registry: trueservice-url:# 表示将自己注册到那个 eureka-serverdefaultZone: http://localhost:9001/eureka

同时我们也需要将该 member-service-provider-10000项目,配置指明为是 Eureka Client 角色,在该项目的场景启动器上添加 注解即可

在这里插入图片描述

package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@EnableEurekaClient 表示将该程序/项目/模块 标识为 eureka-client 端
@EnableEurekaClient
@SpringBootApplication
public class MemberApplication10000 {public static void main(String[] args) {SpringApplication.run(MemberApplication10000.class, args);}
}

测试:

  1. 启动 e-commerce-eureka-server-9001
  2. 启动 member-service-provider-10000
  3. 浏览器: http://localhost:9001

在这里插入图片描述

在这里插入图片描述

3. Service Consumer 、Service Provider 、EurekaServer 的维护机制

示图:

在这里插入图片描述

4. Eureka 自我保护模式

4.1 自我保护模式理论

在默认情况下, Eureka 启动了自我保护模式(如图红字, 需要刷新页面, 可以看到)

在这里插入图片描述

  • 默认情况下EurekaClient 定时向 EurekaServer 端发送 心跳包

  • 如果 Eureka 在 server 端一定时间内(默认90秒) 没有收到 EurekaClient 发送心跳包,便会
    直接从服务注册表中剔除该服务

  • 如果Eureka 开启了**“自我保护机制/模式”** ,那么在短时间(90秒中)内丢失了大量的服务实例心跳。
    这时候Eureka Server 会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通或者
    阻塞)因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的。

  • 自我保护是属于CAP里面的AP分支 ,保证高可用和分区容错性

  • 自我保护模式是一种应对网络异常的安全保护措施,它的架构哲学是宁可同时保留所有微服务(健康
    的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务
    。使用自我保护模式,
    可以让 Eureka 集群更加的健壮,稳定,参考:
    https://blog.csdn.net/wangliangluang/article/details/120626014

  • 一致性: 所有节点在同一时间的数据完全一致
  • 可用性:服务在正常时间内一直可用
  • 分区容错性:系统在遇到节点或者网络分区故障的时候,仍然能够对外满足可用性或一致性的服务

测试:

  • 启动member-service-provider-10000 和 e-commerce-eureka-server-9001

  • 让member-service-provider-10000 正确的注册

  • 然后关闭member-service-provider-10000

  • 观察注册的 member-service-provider-10000 服务是否还在.

在这里插入图片描述

4.2 禁用自我保护模式(生产环境中, 一般不禁用)

演示禁用自我保护模式:

修改 e-commerce-eureka-server-9001 的 application.yml

在这里插入图片描述

修改 member-service-provider-10000 的 application.yml

在这里插入图片描述

启 动 e-commerce-eureka-server-9001 和 member-service-provider-10000

在 member-service-provider-10000 注册成功后,再关闭, 看看 eureka server 服务注册信息的变化

在这里插入图片描述

在这里插入图片描述

提醒:测试完毕后,别忘了恢复原状,启用自我保护

5. 搭建 EurekaServer 集群- 实现负载均衡故障容错

5.1 为什么需要集群 Eureka Server

示意图(上图)
在这里插入图片描述

为什么需要集群 Eureka Server
说明:

  1. 微服务 RPC 远程服务调用最核心的是实习高可用
  2. 如果注册中心只有1个,它出故障,会导致整个服务环境不可用
  3. 解决办法: 搭建 Eureka 注册中心集群,实习 负载均衡 + 故障容错

5.2 需求分析/图解

在这里插入图片描述

5.3 搭建 Eureka Server 集群

1. 创建 e-commerce-eureka-server-9002 微服务模块[作为注册中心]

在这里插入图片描述

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

  1. 修改 pom.xml , 加入依赖

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>e-commerce-center</artifactId><groupId>com.rainbowsea</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>e-commerce-eureka-server-9002</artifactId><dependencies><!--        引入web-starter 说明:这里我们使用版本仲裁(从父项目继承了版本)--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--1. starter-actuator 是spring boot 程序的监控系统,可以实现健康检查,info 信息等2. 访问http://localhost:9002/actuator 可以看到相关链接,还可以做相关配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- 引入 eureka-server 场景启动器 starter: 使用版本仲裁注意:不要搞错了,有一个 starter 的--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!--        lombok 引入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><!--            不进行转递依赖--><optional>true</optional></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency><!--        引入 test-starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        引入我们自己对 bean 封装成 api 的模块内容--><dependency><groupId>com.rainbowsea</groupId><artifactId>e_commerce_center-common-api</artifactId><version>${project.version}</version></dependency></dependencies></project>
  1. 创建 resources/application.yml

在这里插入图片描述

在这里插入图片描述

server:port: 9002
# 配置 eureka server
eureka:instance:hostname: eureka9002.com # 服务实例名/或者叫别名client:# 配置不向注册中心注册自己(因为自己就是注册中心),默认是 trueregister-with-eureka: falsefetch-registry: falseservice-url:#设置与 eureka server 交互的模块,查询服务和注册服务都需要依赖这个地址#      defaultZone: http://localhost:9001/eureka/ ,也可以使用别名,在同一个文件当中可以引用# 相互注册,这里应用注册到 eureka server 9001 上defaultZone: http://eureka9001.com:9001/eureka/
  1. 创建主启动类 EurekaApplication9002.java

在这里插入图片描述

package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer  //该注解标注,当前的项目/模块/程序作为 Eureka Server 角色
public class EurekaApplication9002 {public static void main(String[] args) {SpringApplication.run(EurekaApplication9002.class, args);}
}
  1. 修改 e-commerce-eureka-server-9001 微服务模块,修改其中的内容 resources/application.yml

让: e-commerce-eureka-server-9001 微服务模块 与 e-commerce-eureka-server-9002 相互注册
在这里插入图片描述

在这里插入图片描述

server:port: 9001
# 配置 eureka-server
eureka:instance:hostname: eureka9001.com # 服务实例名或者别名client:# 配置不向注册中心注册自己,默认是 trueregister-with-eureka: false# 表示自己就是注册中心,作用就是维护注册服务实例,不需要去检索服务,默认是 truefetch-registry: falseservice-url:#设置与 eureka server 交互的模块,查询服务和注册服务都需要依赖这个地址#      defaultZone: http://localhost:9001/eureka/ ,也可以使用别名,在同一个文件当中可以引用# 相互注册,这里应用注册到 eureka server 9002 上defaultZone: http://eureka9002.com:9002/eureka/

6. 补充:定义本地的域名机制

如下图所示:
在这里插入图片描述

无论是 9001 还是 9002 ,我们都定义了别名,如果想要,让定义的别名生效的话,我们需要在本地,设置域名映射。

设置本地的域名映射,需要找到本地电脑当中的 host 文件,在该 host文件当中编写添加相应的域名映射。

host文件路径: C:\Windows\System32\drivers\etc\host

在这里插入图片描述

在这里插入图片描述

# 配置 eureka 主机 和 ip 的映射
127.0.0.1 eureka9001.com
127.0.0.1 eureka9002.com
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost127.0.0.1 account.wondershare.com
# 配置 eureka 主机 和 ip 的映射
127.0.0.1 eureka9001.com
127.0.0.1 eureka9002.com

特别提醒:如果发现文件修改后无法保存,那么可以将文件复制到桌面上,然后,修改复制到桌面上的那份复制过来的 host 文件,修改保存完后,再拷贝回原来路径位置,进行一个替换。

运行测试:

  1. 启动 e-commerce-eureka-server-9001
  2. 启动 e-commerce-eureka-server-9002
  3. 浏览器: http://eureka9001.com:9001 浏览器: http://eureka9002.com:9002

在这里插入图片描述

在这里插入图片描述

将 member-service-consumer-80 注册到 EurekaServer 集群(目前 2 台)

修改 member-service-consumer-80 模块当中的:resources/application.yml

在这里插入图片描述

在这里插入图片描述

  1. 启动 e-commerce-eureka-server-9001 和 e-commerce-eureka-server-9002
  2. 启动 member-service-consumer-80
  3. 观察 member-service-consumer-80 是否注册到 Eureka 集群(目前 2 台)

浏览器输入: http://eureka9001.com:9001/

在这里插入图片描述

5.4 搭建会员中心服务提供方-集群

在这里插入图片描述

创建 member-service-provider-10002

参考 member-service-provider-10000 来创建 member-service-provider-10002 即可

创 建 好 后 , 使 用 member-service-provider-10000 的 源 码 和 配 置 替 换 member-service-provider-10002 生成的代码

(不要到磁盘整体拷贝,会出现关联到 member-service-provider-10000 的问题,很麻烦, 可以创建好新项目的包,然后再拷贝对应包下的文件,就不会出问题)

提醒,拷贝时不要忘记拷贝 resources/mapper/MemberMapper.xml 这些 xxx.xml 文 件。

创建 resources/application.yml

创建好 application.yml

从 member-service-provider-10000 拷贝 application.yml 的内容

修改端口号即可

在这里插入图片描述

在这里插入图片描述

server:port: 10002
spring:application:name: member-service-provider # 配置应用的名称datasource:type: com.alibaba.druid.pool.DruidDataSource # 配置 alibaba 的数据库连接池password: MySQL123username: rooturl: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8
mybatis:mapper-locations: classpath:mapper/*.xml # 指定 mapper.xml 文件位置 classpath 表示 resources 目录下type-aliases-package: com.rainbowsea.springcloud.entity # 实例 bean 类所在的包,这样可以通过类名的方式# 配置 eureka-client
eureka:client:register-with-eureka: true # 示将自己注册到 Eureka-Server,因为自己是作为 eureka-client客户端的角色的# 表示从 Eureka-Server 抓取注册信息# 如果是单节点,是可以配置的,但是如果是一个集群,则必须配置true# 才能配合 Ribbon 使用负载均衡fetch-registry: trueservice-url:# 表示将自己注册到那个 eureka-server# 将本微服务注册到多个 eureka - server 当中,使用逗号间隔即可defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/

创建主启动类名(场景启动器)

在这里插入图片描述

启动 eureka server 集群(目前 2 台)

启动 member-service-provider-10000

启动 member-service-provider-10002

浏览器输入: http://eureka9001.com:9001/

在这里插入图片描述

浏览器输入: http://eureka9002.com:9002/

在这里插入图片描述

5.5 配置服务消费端 member-service-consumer-80 使用会员中心服务集群

因为 member-service-provider-10000 和 member-service-provider-10002 作为一个集 群提供服务, 因此需要将 spring.application.name 进行统一,方便用于负载均衡

在这里插入图片描述

这样消费方通过统一的别名进行负载均衡调用。

示意图:

在这里插入图片描述

修改 member-service-consumer-80 模块下的,MemberConsumerController.java

在这里插入图片描述

package com.rainbowsea.springcloud.controller;import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.util.List;@RestController
@Slf4j
public class MemberConsumerController {// 定义 MEMBER_SERVICE_PROVIDER_URL 这是一个基础 url地址// 使用 shift+ctrl+u 进行字母大小写的切换//private static final String MEMBER_SERVICE_PROVIDER_URL = "http://localhost:10000";// 负载均衡统一别名,修改为提供服务模块的注册别名: 不需要配置指明端口号,因为是一个负载集群了。不是特指某个了Service 服务来处理了/*server:port: 10000
spring:application:name: member-service-provider # 配置应用的名称*//*说明:1. MEMBER-SERVICE-PROVIDER 就是服务提供方【集群】,注册到Eureka Server 的名称2. 也就是服务提供方【集群】对外暴露的名称为 MEMBER-SERVICE-PROVIDER3. MEMBER-SERVICE-PROVIDER 目前有两个 	Availability Zones 	UP (2) - localhost:member-service-provider:10000 , localhost:member-service-provider:10002还有一个 member-service-provider:10002需要增加一个注解 @LoadBalanced 赋予 RestTemplate 才能有负载均衡的能力,也就是会根据你的负载均衡来选择某个服务去访问,默认是“轮询算法”,当然我们也可以自己配置负载均衡算法4. 在对应的 RestTemplate 配置类上的,@Bean注解下面加上 @LoadBalanced 注解。*/private static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";// 装配 RestTemplate bean/对象@Resourceprivate RestTemplate restTemplate;@PostMapping("/member/consumer/save")public Result<Member> save(Member member) {// 1.第1个参数: 就是请求的完整的url:MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save// 表示你向将该请求,发送给那个微服务处理,注意无论是返回值,还是参数, @PostMapping() 请求方式都要一一对应上对应处理的微服务上的内容//2. 第2个参数: member : 就是通过 restTemplate 发出的 post 请求携带数据或者对象//3. 第3个参数: Result.class ,微服务当中的对应处理的方法的,返回值,也就是返回对象类型// 注意:坑点// 这里通过 restTemplate 调用服务模块的接口,就是一个远程调用//log.info("member-service-consumer-80 save member={}", member);return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}/*1.与@PostMapping("/member/save")public Result save(Member member) {int affected = memberService.save(member);if (affected > 0) { // 说明添加成功return Result.success("添加会员成功", affected);} else {return Result.error("401", "添加会员失败");}}*//*** 方法/接口,调用服务接口,返回 member 对象信息** @param id* @return*/@GetMapping("/member/consumer/get/{id}")public Result<Member> getMemberById(@PathVariable("id") Long id) {// 这里就用两个参数// 第一个参数,因为是查询,所以这里我们直接字符串拼接上去// 这里通过return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id, Result.class);}/*保持一致:* 提交方式* 返回类型* 参数* 路径映射要对应上@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功", member);} else {return Result.error("402", "ID" + id + "不存在");}}*/// 注意:有两个是这个包下的 : org.springframework.cloud.client.discovery.DiscoveryClient@Resource // 装配到 Spring ioc 容器当中private DiscoveryClient discoveryClient;// 注意:想要获取到服务端信息,还需要在SpringBoot 启动场景上加上:@EnableDiscoveryClient // 启用服务发现 注解才行@GetMapping("/member/consumer/discovery")public Object discovery(){List<String> services = discoveryClient.getServices();// 遍历 servicesfor (String service : services) {log.info("服务名==={}",service);// 再根据服务名获取更加详细的信息List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {log.info("id={},host={},uri={}",instance.getServiceId(),instance.getHost(),instance.getUri());}}return this.discoveryClient;}
}

为了看到测试效果,修改服务提供方

在两个服务提供方的查询和添加返回结果处增加自己服务名称信息,如图, 其它位置可参考加入

在这里插入图片描述

    /*** 这里我们使用 url占位符 + @PathVariable** @param id* @return*/@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功 member-service-provider-10000 ", member);} else {return Result.error("402", "ID" + id + "不存在 member-service-provider-10000 ");}}
/*** 这里我们使用 url占位符 + @PathVariable** @param id* @return*/@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功 member-service-provider-10002 ", member);} else {return Result.error("402", "ID" + id + "不存在 member-service-provider-10002  ");}}

特别说明: 我们想要能够实现 member 交替访问的话,需要在 RestTemplate 配置类上@Bean方法上加上该 @LoadBalanced注解的)才行。
底层是 Ribbon 支持算法 交替访问 member服务说明:

  1. 注解@LoadBalanced(在RestTemplate 配置类的@Bean方法上加上该 @LoadBalanced注解的)
    底层是 Ribbon 支持算法

在这里插入图片描述

  1. Ribbon 和 Eureka 整合后 consumer 直接调用服务而不用再关心地址和端口号,且该服务还有负载功能

运行测试:

启动 member-service-consumer-80

浏览器访问:http://eureka9001.com:9001/

在这里插入图片描述

浏览器访问: http://localhost/member/consumer/get/1 这个是通过客户端 Eureka Client 发送的请求路径映射:

在这里插入图片描述

在这里插入图片描述

5.6 获取 Eureka Server 服务注册信息 - DiscoveryClient

先看需求分析示意图:

在这里插入图片描述

这里我们以服务消费方 去获取 Eureka Server 的服务注册信息为例讲解

在这里插入图片描述

当然也可以在服务提供方获取 Eureka Server 的服务注册信息。

5.5.1 具体操作步骤:

所在模块 member-service-consumer-80,修改:com.rainbowsea.springcloud.controller.MemberConsumerController 包当中的

增加如下代码:

在这里插入图片描述

 @Resource // 装配到 Spring ioc 容器当中private DiscoveryClient discoveryClient;// 注意:想要获取到服务端信息,还需要在SpringBoot 启动场景上加上:@EnableDiscoveryClient // 启用服务发现 注解才行@GetMapping("/member/consumer/discovery")public Object discovery(){List<String> services = discoveryClient.getServices();// 遍历 servicesfor (String service : services) {log.info("服务名==={}",service);// 再根据服务名获取更加详细的信息List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {log.info("id={},host={},uri={}",instance.getServiceId(),instance.getHost(),instance.getUri());}}return this.discoveryClient;}
package com.rainbowsea.springcloud.controller;import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.util.List;@RestController
@Slf4j
public class MemberConsumerController {// 定义 MEMBER_SERVICE_PROVIDER_URL 这是一个基础 url地址// 使用 shift+ctrl+u 进行字母大小写的切换//private static final String MEMBER_SERVICE_PROVIDER_URL = "http://localhost:10000";// 负载均衡统一别名,修改为提供服务模块的注册别名: 不需要配置指明端口号,因为是一个负载集群了。不是特指某个了Service 服务来处理了/*server:port: 10000
spring:application:name: member-service-provider # 配置应用的名称*//*说明:1. MEMBER-SERVICE-PROVIDER 就是服务提供方【集群】,注册到Eureka Server 的名称2. 也就是服务提供方【集群】对外暴露的名称为 MEMBER-SERVICE-PROVIDER3. MEMBER-SERVICE-PROVIDER 目前有两个 	Availability Zones 	UP (2) - localhost:member-service-provider:10000 , localhost:member-service-provider:10002还有一个 member-service-provider:10002需要增加一个注解 @LoadBalanced 赋予 RestTemplate 才能有负载均衡的能力,也就是会根据你的负载均衡来选择某个服务去访问,默认是“轮询算法”,当然我们也可以自己配置负载均衡算法4. 在对应的 RestTemplate 配置类上的,@Bean注解下面加上 @LoadBalanced 注解。*/private static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";// 装配 RestTemplate bean/对象@Resourceprivate RestTemplate restTemplate;@PostMapping("/member/consumer/save")public Result<Member> save(Member member) {// 1.第1个参数: 就是请求的完整的url:MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save// 表示你向将该请求,发送给那个微服务处理,注意无论是返回值,还是参数, @PostMapping() 请求方式都要一一对应上对应处理的微服务上的内容//2. 第2个参数: member : 就是通过 restTemplate 发出的 post 请求携带数据或者对象//3. 第3个参数: Result.class ,微服务当中的对应处理的方法的,返回值,也就是返回对象类型// 注意:坑点// 这里通过 restTemplate 调用服务模块的接口,就是一个远程调用//log.info("member-service-consumer-80 save member={}", member);return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}/*1.与@PostMapping("/member/save")public Result save(Member member) {int affected = memberService.save(member);if (affected > 0) { // 说明添加成功return Result.success("添加会员成功", affected);} else {return Result.error("401", "添加会员失败");}}*//*** 方法/接口,调用服务接口,返回 member 对象信息** @param id* @return*/@GetMapping("/member/consumer/get/{id}")public Result<Member> getMemberById(@PathVariable("id") Long id) {// 这里就用两个参数// 第一个参数,因为是查询,所以这里我们直接字符串拼接上去// 这里通过return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id, Result.class);}/*保持一致:* 提交方式* 返回类型* 参数* 路径映射要对应上@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功", member);} else {return Result.error("402", "ID" + id + "不存在");}}*/// 注意:有两个是这个包下的 : org.springframework.cloud.client.discovery.DiscoveryClient@Resource // 装配到 Spring ioc 容器当中private DiscoveryClient discoveryClient;// 注意:想要获取到服务端信息,还需要在SpringBoot 启动场景上加上:@EnableDiscoveryClient // 启用服务发现 注解才行@GetMapping("/member/consumer/discovery")public Object discovery(){List<String> services = discoveryClient.getServices();// 遍历 servicesfor (String service : services) {log.info("服务名==={}",service);// 再根据服务名获取更加详细的信息List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {log.info("id={},host={},uri={}",instance.getServiceId(),instance.getHost(),instance.getUri());}}return this.discoveryClient;}
}
  1. 这里修改所在模块 member-service-consumer-80当中的主启动类(场景启动类) com.rainbowsea.springcloud.MemberConsumerApplication80

在这里插入图片描述

package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;// 如果错误: 加入排除 DataSourceAutoConfiguration 自动配置
//@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
//@EnableEurekaClient 表示将项目/模块/程序 标注作为 Eureka Client
@EnableEurekaClient
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class MemberConsumerApplication80 {public static void main(String[] args) {SpringApplication.run(MemberConsumerApplication80.class, args);}
}

重启 member-service-consumer-80

浏览器输出 http://localhost/member/consumer/discovery
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.5.1.1 注意事项和细节说明

在引入 DiscoveryClient 时,不要引入错误的包
正确的包: import org.springframework.cloud.client.discovery.DiscoveryClient;
错误的包: import com.netflix.discovery.DiscoveryClient;

在这里插入图片描述

演示的是在服务消费方使用 DiscoveryClient 来完成服务发现,同样,在服务提供 方/模块也 OK

7. Eureka 后续说明

  1. Eureka 停更说明: https://github.com/Netflix/eureka/wiki

在这里插入图片描述

  1. 对于一些早期使用 Eureka 项目,掌握老师讲解技术基本可以应付了(这也是老师为什么还要讲Eureka的原因)

  2. 目前替代Eureka做服务注册和发现均衡负载的最佳组件是Nacos , 后面会重点讲解
    Spring Cloud Alibaba

  3. 虽然 Eureka 停更,目前用的不多,但是它的服务注册和发现均衡负载的思想是优先
    的,有了Eureka的基础,我们学习Spring Cloud Alibaba Nacos会轻松很多

8. 总结:

  1. Spring Cloud Eureka 服务注册于发现
  2. Eureka 自我保护模式
  • 默认情况下EurekaClient 定时向 EurekaServer 端发送 心跳包

  • 如果 Eureka 在 server 端一定时间内(默认90秒) 没有收到 EurekaClient 发送心跳包,便会
    直接从服务注册表中剔除该服务

  • 如果Eureka 开启了**“自我保护机制/模式”** ,那么在短时间(90秒中)内丢失了大量的服务实例心跳。
    这时候Eureka Server 会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通或者
    阻塞)因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的。

  • 自我保护是属于CAP里面的AP分支 ,保证高可用和分区容错性

  • 自我保护模式是一种应对网络异常的安全保护措施,它的架构哲学是宁可同时保留所有微服务(健康
    的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务
    。使用自我保护模式,
    可以让 Eureka 集群更加的健壮,稳定,参考:
    https://blog.csdn.net/wangliangluang/article/details/120626014

在生产环境中,一般不会禁用自我保护模式

  1. Eureka 集群-实现负载均衡,故障容错

为什么需要集群 Eureka Server
说明:

  1. 微服务 RPC 远程服务调用最核心的是实习高可用
  2. 如果注册中心只有1个,它出故障,会导致整个服务环境不可用
  3. 解决办法: 搭建 Eureka 注册中心集群,实习 负载均衡 + 故障容错

因为 member-service-provider-10000 和 member-service-provider-10002 作为一个集 群提供服务, 因此需要将 spring.application.name 进行统一,方便用于负载均衡

在这里插入图片描述

这样消费方通过统一的别名进行负载均衡调用。

在这里插入图片描述

特别说明: 我们想要能够实现 member 交替访问的话,需要在 RestTemplate 配置类上@Bean方法上加上该 @LoadBalanced注解的)才行。 底层是 Ribbon 支持算法 交替访问 member服务说明:

注解@LoadBalanced(在RestTemplate 配置类的@Bean方法上加上该 @LoadBalanced注解的) 底层是 Ribbon 支持算法

在这里插入图片描述

Ribbon 和 Eureka 整合后 consumer 直接调用服务而不用再关心地址和端口号,且该服务还有负载功能

  1. 定义本地的域名机制:

设置本地的域名映射,需要找到本地电脑当中的 host 文件,在该 host文件当中编写添加相应的域名映射。

host文件路径: C:\Windows\System32\drivers\etc\host

在这里插入图片描述


127.0.0.1 account.wondershare.com
# 配置 eureka 主机 和 ip 的映射
127.0.0.1 eureka9001.com
127.0.0.1 eureka9002.com

特别提醒:如果发现文件修改后无法保存,那么可以将文件复制到桌面上,然后,修改复制到桌面上的那份复制过来的 host 文件,修改保存完后,再拷贝回原来路径位置,进行一个替换。

  1. 获取 Eureka Server 服务注册信息 - DiscoveryClient;在引入 DiscoveryClient 时,不要引入错误的包,正确的包: import org.springframework.cloud.client.discovery.DiscoveryClient;

9. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

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

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

相关文章

视频孪生技术在金融银行网点场景中的应用价值

作为国民经济重要的基础行业&#xff0c;金融行业在高速发展的同时衍生出业务纠纷、安全防范、职能管理等诸多问题&#xff0c;对安全防范和监督管理提出了更高的要求。因此&#xff0c;如何能更好的利用视频监控系统价值&#xff0c;让管理人员更简便的浏览监控视频、更快速的…

武汉EI学术会议一览表

武汉近期将举办BDDM2024大数据会议、ASIM2024智能制造会议、ICSGPS2025电网会议&#xff0c;吸引国内外学者参与&#xff0c;推动科技创新与产业发展&#xff0c;录用论文将提交EI索引。 武汉EI学术会议一览表 1.第二届大数据与数据挖掘国际会议&#xff08;BDDM 2024&#xf…

LeetCode Hot100 15.三数之和

题干&#xff1a; 思路&#xff1a; 首先想到的是哈希表&#xff0c;类似于两数之和的想法&#xff0c;共两层循环&#xff0c;将遍历到的第一个元素和第二个元素存入哈希表中&#xff0c;然后按条件找第三个元素&#xff0c;但是这道题有去重的要求&#xff0c;哈希表实现较为…

html + css 自适应首页布局案例

文章目录 前言一、组成二、代码1. css 样式2. body 内容3.全部整体 三、效果 前言 一个自适应的html布局 一、组成 整体居中&#xff0c;宽度1200px&#xff0c;小屏幕宽度100% 二、代码 1. css 样式 代码如下&#xff08;示例&#xff09;&#xff1a; <style>* {…

使用Axios函数库进行网络请求的使用指南

目录 前言1. 什么是Axios2. Axios的引入方式2.1 通过CDN直接引入2.2 在模块化项目中引入 3. 使用Axios发送请求3.1 GET请求3.2 POST请求 4. Axios请求方式别名5. 使用Axios创建实例5.1 创建Axios实例5.2 使用实例发送请求 6. 使用async/await简化异步请求6.1 获取所有文章数据6…

MySQL —— MySQL索引介绍、索引数据结构、聚集索引和辅助索引、索引覆盖

文章目录 索引概念索引分类索引数据结构种类Innodb 索引数据结构聚集索引和辅助索引&#xff08;非聚集索引&#xff09;聚集索引辅助索引&#xff08;非聚集索引&#xff09; 索引覆盖 索引概念 索引是对数据库表中一列或多列的值进行排序后的一种数据结构。用于帮助 mysql 提…

python实现十进制转换二进制,tkinter界面

目录 需求 效果 代码实现 代码解释 需求 python实现十进制转换二进制 效果 代码实现 import tkinter as tk from tkinter import messageboxdef convert_to_binary():try:# 获取输入框中的十进制数decimal_number int(entry.get())# 转换为二进制binary_number bin(de…

机器学习—正则化和偏差或方差

正则化参数的选择对偏差和方差的影响 用一个四阶多项式&#xff0c;要用正则化拟合这个模型&#xff0c;这里的lambda的值是正则化参数&#xff0c;它控制着你交易的金额&#xff0c;保持参数w与训练数据拟合&#xff0c;从将lambda设置为非常大的值的示例开始&#xff0c;例如…

在Node.js中如何使用TypeScript

第一步&#xff1a;创建一个Node.js项目的package.json文件 npm init -y第二步&#xff1a;添加TypeScript、添加node.d.ts npm install typescript -D npm install types/node -D第三步&#xff1a;初始化一个tsconfig.json文件 npx tsc --init --rootDir src --outDir lib…

零基础Java第十九期:认识String(一)

目录 一、String的重要性 二、String的常用方法 2.1. 字符串构造 2.2. String对象的比较 2.3. 字符串查找 2.4. 转化 2.4. 字符串替换 2.5. 字符串拆分 2.6. 字符串截取 一、String的重要性 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能…

面试经典 150 题:20、2、228、122

20. 有效的括号 参考代码 #include <stack>class Solution { public:bool isValid(string s) {if(s.size() < 2){ //特判&#xff1a;空字符串和一个字符的情况return false;}bool flag true;stack<char> st; //栈for(int i0; i<s.size(); i){if(s[i] ( |…

【SpringBoot】公共字段自动填充

问题引入 JavaEE开发的时候&#xff0c;新增字段&#xff0c;修改字段大都会涉及到创建时间(createTime)&#xff0c;更改时间(updateTime)&#xff0c;创建人(craeteUser)&#xff0c;更改人(updateUser)&#xff0c;如果每次都要自己去setter()&#xff0c;会比较麻烦&#…

深度学习-卷积神经网络CNN

案例-图像分类 网络结构: 卷积BN激活池化 数据集介绍 CIFAR-10数据集5万张训练图像、1万张测试图像、10个类别、每个类别有6k个图像&#xff0c;图像大小32323。下图列举了10个类&#xff0c;每一类随机展示了10张图片&#xff1a; 特征图计算 在卷积层和池化层结束后, 将特征…

stm32——通用定时器时钟知识点

&#xff08;该图来自小破站 铁头山羊老师的stm32标准库教学&#xff09;

SobarQube实现PDF报告导出

文章目录 前言一、插件配置二、使用步骤1.新生成一个Token2.将拷贝的Token加到上文中执行的命令中3.查看报告 三、友情提示总结 前言 这篇博文是承接此文 .Net项目在Windows中使用sonarqube进行代码质量扫描的详细操作配置 描述如何导出PDF报告 众所周知&#xff0c;导出PDF功…

【数据结构】10.线索二叉树

一、线索二叉树的产生 采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列&#xff0c;序列上的每一个结点&#xff08;除了第一个和最后一个&#xff09;都有一个前驱和一个后继&#xff0c;但是&#xff0c;这个线性序列只是逻辑的概念&#xff0c;不是物理结…

如何合理设计一套springcloud+springboot项目中的各个微服务模块之间的继承关系的最优方案

文章目录 一、模块化设计所遵循的原则二、项目架构设计三、各个模块作用说明3.1 core 模块3.2 common 模块3.3 generatorcode模块3.4 business 模块3.5 web 模块3.6 admin 模块3.7 父pom 四、采用import引入SpringBoot 在springcloud微服务项目中经常用到多模块化的架构设计&am…

HarmonyOS4+NEXT星河版入门与项目实战--------开发工具与环境准备

文章目录 1、熟悉鸿蒙官网1、打开官网2、下载 DevEco Studio3、HarmonyOS 资源库4、开发指南与API 2、安装 DevEco Studio1、软件安装2、配置开发工具 1、熟悉鸿蒙官网 1、打开官网 百度搜索 鸿蒙开发者官网 点击进入开发者官网&#xff0c;点击开发&#xff0c;可以看到各种…

单元测试、集成测试、系统测试、验收测试、压力测试、性能测试、安全性测试、兼容性测试、回归测试(超详细的分类介绍及教学)

目录 1.单元测试 实现单元测试的方法&#xff1a; 注意事项&#xff1a; 2.集成测试 需注意事项&#xff1a; 实现集成测试的方法&#xff1a; 如何实现高效且可靠的集成测试&#xff1a; 3.系统测试 实现系统测试的方法: 须知注意事项&#xff1a; 4.验收测试 实现验…

Ubuntu24 上安装搜狗输入法

link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页​ shurufa.sogou.com/linux 找到刚才下…