微服务框架 SpringCloud微服务架构3
微服务框架 SpringCloud微服务架构
3 Eureka
3.1 提供者与消费者
3.1.1 一些概念
- 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
- 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
在我们的Demo案例中
很明显两者是如下的关系:
3.1.2 一个问题
假设现在服务A调用服务B,服务B调用服务C,那么服务B是什么角色?
【相对概念】【抛开业务来谈提供者和消费者的概念是不应该的,即一个服务既可以是提供者也可以是消费者】
3.1.3 总结
服务调用关系
- 服务提供者:暴露接口给其它微服务调用
- 服务消费者:调用其它微服务提供的接口
- 提供者与消费者角色其实是相对的
- 一个服务可以同时是服务提供者和服务消费者.
Eureka 3.2 Eureka 原理分析
3.2.1 服务调用出现的问题
在我们之前的Demo 案例中,出现了下图所示的调用情况
而且是采用硬编码的形式,把IP和端口告诉order 服务
这样也很容易地就带来一些问题,这样写死了,环境改变了怎么办?耦合度巨高
而且随着服务的高并发,user 服务可能会部署成多个实例,
这样时候,硬编码咋办?【所以这里一定不能用硬编码】
【归结一个问题:服务消费者到底应该如何获取服务提供者的地址信息?】
而且有一天,咱们真的拿到了它们每台的地址,有多个服务提供者的情况,消费者又该如何选择?
而且,消费者又如何得知服务提供者的健康状态? 【…一堆的问题】
【这个时候就可以请出 Eureka了】
3.2.2 Eureka 的作用
一个服务端,一个客户端
在每一个 user-service 和 order-service 启动的那一刻,会把自己的信息注册给Eureka
现在当有消费者想要消费服务时,就直接找Eureka
这样第一个问题 【服务消费者到底应该如何获取服务提供者的地址信息】 就解决了
接着通过负载均衡,从三个中挑一个出来
再接下去,就可以发请求了
【怎么保证服务是健康的?】
心跳续约,每30 s 一次,来让注册中心确认自己的状态
如果说有天 user-service 8083 没跳了,注册中心就会把它从信息中删除
order-service 再次拉取服务信息时,就不会拉到8083 了
【即消费者可以监控到服务提供者的状态】
回顾一下“三个问题”
1、消费者该如何获取服务提供者具体信息?
- 服务提供者启动时向eureka注册自己的信息
- eureka保存这些信息
- 消费者根据服务名称向eureka拉取提供者信息
2、如果有多个服务提供者,消费者该如何选择?
- 服务消费者利用负载均衡算法,从服务列表中挑选一个
3、消费者如何感知服务提供者健康状态?
- 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
- eureka会更新记录服务列表信息,心跳不正常会被剔除
- 消费者就可以拉取到最新的信息
3.2.3 总结
在Eureka架构中,微服务角色有两类:
- EurekaServer:服务端,注册中心
- 记录服务信息
- 心跳监控
- EurekaClient:客户端
- Provider:服务提供者,例如案例中的 user-service
- 注册自己的信息到EurekaServer
- 每隔30秒向EurekaServer发送心跳
- consumer:服务消费者,例如案例中的 order-service
- 根据服务名称从EurekaServer拉取服务列表
- 基于服务列表做负载均衡,选中一个微服务后发起远程调用
- Provider:服务提供者,例如案例中的 user-service
Eureka 3.3 搭建 Eureka 服务
3.3 搭建 Eureka 服务
3.3.1 动手实践
三件事
3.3.2 搭建EurekaServer
搭建EurekaServer 服务步骤如下
注意:
由于 Spring Boot 3.0,Spring Boot 2.7~2.4 和 2.4 以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 3.0 和 2.4 分别为分界线,同时维护 2022.x、2021.x、2.2.x 三个分支迭代。如果不想跨分支升级,如需使用新特性,请升级为对应分支的新版本。 为了规避相关构建过程中的依赖冲突问题,
2022.x 分支
适配 Spring Boot 3.0,Spring Cloud 2022.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): (注意,该分支 Spring Cloud Alibaba 版本命名方式进行了调整,未来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最后一位为扩展版本,比如适配 Spring Cloud 2022.0.0 版本对应的 Spring Cloud Alibaba 第一个版本为:2022.0.0.0,第个二版本为:2022.0.0.1,依此类推)
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2022.0.0.0-RC2* |
Spring Cloud 2022.0.0 |
3.0.2 |
2022.0.0.0-RC1 |
Spring Cloud 2022.0.0 |
3.0.0 |
2021.x 分支
适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2021.0.5.0* |
Spring Cloud 2021.0.5 |
2.6.13 |
2021.0.4.0 |
Spring Cloud 2021.0.4 |
2.6.11 |
2021.0.1.0 |
Spring Cloud 2021.0.1 |
2.6.3 |
2021.1 |
Spring Cloud 2020.0.1 |
2.4.2 |
① 创建项目,引入spring-cloud-starter-netflix-eureka-server的依赖
直接在已有工程中创建一个新的模块
导入依赖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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tongda</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 这里控制了 springcloud 的版本--> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.7.8</spring-boot.version> <spring-cloud.version>2021.0.5</spring-cloud.version> </properties> <dependencies> <!-- eureka 注册中心的服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 依赖管理,cloud 的依赖--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>com.tongda.EurekaServerApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> </execution> </executions> </plugin> </plugins> </build> </project>
分析端口 8761
4.2 搭建 Eureka-client
4.2.1 创建项目 client-a 选择 依赖.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
# 应用服务 WEB 访问端口没有要求、随意 server: port: 8080 spring: application: name: eureka-client # 注册的含义是什么?就是将自己的一些信息(什么信息IP port....)发送过去(发到那里) eureka: client: service-url: # 指定注册地址 defaultZone: http://localhost:8761/eureka
4.3.2 访问查看
4.4 注册中心的状态认识
4.4.1 服务的实例名称
4.5 常用配置文件设置
4.5.1 server 中常用的配置
# 单机 server: port: 8761 # eureka默认端口 spring: application: name: eurekaserver # eureka的服务名称,不要使用特殊字符 eureka: # eureka的配置分为三类server client 实例的 client: service-url: # eureka的地址信息 # defaultZone: http://localhost:8761/eureka # 避免写死 defaultZone: ${EUREKA_SERVER_URL:http://localhost:8761/eureka} # register-with-eureka: false #先将server自己注册自己的开关 关掉 register-with-eureka: ${REGISTER-WITH-EUREKA:true} #先将server自己注册自己的开关 关掉 fetch-registry: true # docker run -p 端口 -d 后台运行 --link 指定网络host文件映射的 -e MYSQL_ROOT_PASSWORD=123456 临时指定 -v 文件挂载 server: eviction-interval-timer-in-ms: 10000 #服务器间隔多少毫秒做定期删除的操作 renewal-percent-threshold: 0.85 #续约百分比,超过85%的应用没有和你续约,那么eureka会保护服务,不会剔除任何一个 instance: # 实例的配置 # instance-id: localhost:eureka-server:8761 # 主机名称:应用名称:端口号 instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 避免写死 hostname: localhost # 主机名称或者服务的ip prefer-ip-address: true # 以ip的形式显示具体的服务信息 lease-renewal-interval-in-seconds: 5 # 服务实例的续约的时间间隔 #集群 #server: # port: 8761 #spring: # application: # name: eureka-server #eureka: # client: # service-url: # 不写会自动注册8761 # defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka # # instance: # 实例的配置 # # instance-id: localhost:eureka-server:8761 # 主机名称:应用名称:端口号 # instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 避免写死 # hostname: localhost # 主机名称或者服务的ip,此处为集群主机名可以不写 # prefer-ip-address: true # 以ip的形式显示具体的服务信息 # lease-renewal-interval-in-seconds: 5 # 服务实例的续约的时间间隔 #集群终极方案 #server: # port: 8761 # eureka的默认端口 #spring: # application: # name: eureka-server # 应用名称,不要使用特殊字符 #eureka: # client: # service-url: #不写默认端口8761 ## defaultZone: http://peer1:8761/eureka,http://peer2:8762/eureka,http://peer3:8763/eureka # defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka,http://localhost:8763/eureka # instance: # instance-id: ${spring.application.name}:${server.port} #主机名称:应用名称:端口 ## hostname: peer1 # 主机名称或者服务的ip,此处为集群主机名可以不写 # prefer-ip-address: true # 以ip的形式显示具体的服务信息 # lease-renewal-interval-in-seconds: 5 # 服务实例的续约的时间间隔
4.5.2 client 中常用的配置
server: port: 8763 spring: application: name: eureka-server # 集群时应用名称不能改 eureka: client: service-url: # eureka 服务端和客户端的交互地址,集群用,隔开 defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka register-with-eureka: true #注册自己 fetch-registry: true #拉取服务列表 registry-fetch-interval-seconds: 5 # 表示 eureka-client 间隔多久去拉取服务注册信息 instance: # 实例的配置 # instance-id: localhost:eureka-server:8761 # 主机名称:应用名称:端口号 instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 避免写死 hostname: localhost # 主机名称或者服务的ip prefer-ip-address: true # 以ip的形式显示具体的服务信息 lease-renewal-interval-in-seconds: 5 # 服务实例的续约的时间间隔 lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例
5.构建高可用的 Eureka-Server 集群
1、中心化集群
2、主从模式集群
3、去中心化集群:高可用
在去中心化模式中没有主从的概念,自己可以注册自己,实现两两注册达到高可用集群
5.1 对刚才的 eureka-server 修改配置文件
5.1.1 server-1
5.1.2 server-2
集群的深刻理解