SpringCloud之Eureka、Ribbon及Nacos
文章目录
- SpringCloud之Eureka、Ribbon及Nacos
- 1. 单体架构和微服务架构
- 2. SpringBoot、SpringCloud及SpringCloud Alibaba之间的版本对应关系
- 2022.x 分支
- 2021.x 分支
- 2.2.x 分支
- 组件版本关系
- 3. Eureka
- 3.1 Eureka-server注册中心
- 3.2 Eureka-client客户端
- 4. Ribbon
- 5. RestTemplate
- 6. Nacos
- 6.1 Nacos的安装
- 6.2 服务注册到Nacos
- 6.2.1 引入依赖
- 6.2.2 配置nacos地址
- 6.3 服务分级存储模型
- 6.3.1 配置集群
- 6.3.2 同集群优先的负载均衡
- 6.4 权重配置
- 6.5 环境隔离
- 6.5.1 创建namespace
- 6.5.2 给微服务配置namespace
- 6.6 Nacos与Eureka的区别
- 7. 代码示例
- 7.1 父工程pom文件
- 7.2 Eureka示例
- 7.2.1 服务端服务模块pom文件
- 7.2.2 服务端服务模块application配置文件
- 7.2.3 服务端服务模块主启动类
- 7.2.4 客户端服务模块pom文件
- 7.2.5 客户端服务模块application配置文件
- 7.2.6 客户端服务模块主启动类
- 7.3 Nacos示例
- 7.3.1 客户端服务模块pom文件
- 7.3.2 客户端服务模块application文件
- 7.3.3 客户端服务模块主启动类
1. 单体架构和微服务架构
单体架构: 将业务的所有功能集中在一个项目中开发,打成一个包部署。
单体架构的优缺点:
优点:
- 架构简单
- 部署成本低
缺点:
- 模块之间的耦合程度高,维护困难,功能升级困难
微服务架构: 根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,作为一个服务。
微服务架构的优缺点:
优点:
- 服务之间的耦合程度降低
- 有利于服务升级与扩展
缺点:
- 服务调用关系错综复杂
2. SpringBoot、SpringCloud及SpringCloud Alibaba之间的版本对应关系
由于 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-RC* | 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.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 |
2.2.x 分支
适配 Spring Boot 为 2.4,Spring Cloud Hoxton 版本及以下的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2.2.10-RC1* | Hoxton.SR12 | 2.3.12.RELEASE |
2.2.9.RELEASE | Hoxton.SR12 | 2.3.12.RELEASE |
2.2.8.RELEASE | Hoxton.SR12 | 2.3.12.RELEASE |
2.2.7.RELEASE | Hoxton.SR12 | 2.3.12.RELEASE |
2.2.6.RELEASE | Hoxton.SR9 | 2.3.2.RELEASE |
2.2.1.RELEASE | Hoxton.SR3 | 2.2.5.RELEASE |
2.2.0.RELEASE | Hoxton.RELEASE | 2.2.X.RELEASE |
2.1.4.RELEASE | Greenwich.SR6 | 2.1.13.RELEASE |
2.1.2.RELEASE | Greenwich | 2.1.X.RELEASE |
2.0.4.RELEASE(停止维护,建议升级) | Finchley | 2.0.X.RELEASE |
1.5.1.RELEASE(停止维护,建议升级) | Edgware | 1.5.X.RELEASE |
组件版本关系
每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示(注意,Spring Cloud Dubbo 从 2021.0.1.0 起已被移除出主干,不再随主干演进):
Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version |
---|---|---|---|---|---|
2.2.10-RC1 | 1.8.6 | 2.2.0 | 4.9.4 | ~ | 1.6.1 |
2022.0.0.0-RC1 | 1.8.6 | 2.2.1-RC | 4.9.4 | ~ | 1.6.1 |
2.2.9.RELEASE | 1.8.5 | 2.1.0 | 4.9.4 | ~ | 1.5.2 |
2021.0.4.0 | 1.8.5 | 2.0.4 | 4.9.4 | ~ | 1.5.2 |
2.2.8.RELEASE | 1.8.4 | 2.1.0 | 4.9.3 | ~ | 1.5.1 |
2021.0.1.0 | 1.8.3 | 1.4.2 | 4.9.2 | ~ | 1.4.2 |
2.2.7.RELEASE | 1.8.1 | 2.0.3 | 4.6.1 | 2.7.13 | 1.3.0 |
2.2.6.RELEASE | 1.8.1 | 1.4.2 | 4.4.0 | 2.7.8 | 1.3.0 |
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE | 1.8.0 | 1.4.1 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE | 1.8.0 | 1.3.3 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE | 1.7.1 | 1.2.1 | 4.4.0 | 2.7.6 | 1.2.0 |
2.2.0.RELEASE | 1.7.1 | 1.1.4 | 4.4.0 | 2.7.4.1 | 1.0.0 |
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE | 1.7.0 | 1.1.4 | 4.4.0 | 2.7.3 | 0.9.0 |
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE | 1.6.3 | 1.1.1 | 4.4.0 | 2.7.3 | 0.7.1 |
最早使用SpringCloud版本的时候,直接将查找出来的版本当作version放在dependency中,导致maven导包的时候一直报包找不到的错误,后经查阅发现SpringCloud Version是要放在dependencyManagement中进行统一管理的。
最佳使用方式:
先创建一个父工程,并在父工程的pom中将改成pom的形式,如下所示:
<groupId>com.example</groupId>
<artifactId>my-cloud-demo</artifactId>
<packaging>pom</packaging>
<version>0.0.1</version>
然后新建子模块后,把子模块统一加入父工程modules管理,如下所示:
<modules>
<module>order-service</module>
<module>user-service</module>
<module>eureka-server</module>
</modules>
这样子模块就可以导入父工程所引入的依赖了。
最后在dependencyManagement中添加如下,此处的spring-boot.version及spring-cloud.version均可以在如上的依赖关系表中查到:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3. Eureka
3.1 Eureka-server注册中心
首先配置eureka-server注册中心:
spring:
application:
name: eureka-server
# 微服务的端口
server:
port: 8050
eureka:
# ip地址,不配的话默认为localhost
instance:
hostname: localhost
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从eureka中获取注册信息
fetch-registry: false
# 配置暴露给Eureka Client的请求地址
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
然后在eureka-server的主启动类上加入 @EnableEurekaServer的注解。
3.2 Eureka-client客户端
配置eureka-client客户端:
spring:
application:
name: order-service
# 微服务的端口
server:
port: 8070
eureka:
client:
service-url:
# 添加Eureka Server的主机地址
defaultZone: http://127.0.0.1:8050/eureka
instance:
# 默认服务端每隔30s向注册中心发送一次心跳,此处更改发送间隔为10s
lease-renewal-interval-in-seconds: 10
# 续约到期时间,若超过该时间注册中心未收到服务的心跳,则认为续约到期
lease-expiration-duration-in-seconds: 20
# 使用ip注册
prefer-ip-address: true
# 注册的ID使用ip
instance-id: ${spring.cloud.client.ip-address}:${server.port}
# 开启健康检查,需要引入actuator依赖
healthcheck.enabled: true
开启健康检查需导入actuator依赖:
<!--开启健康检测,在客户端定义-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后在eureka-server的主启动类上加入 @EnableEurekaClient的注解。
具体配置控制在eureka页面上显示如下:
4. Ribbon
Ribbon主要用来实现负载均衡功能。
如在order-service中需对调用user-service服务的行为进行负载均衡,配置如下:
user-service:
ribbon:
# Ribbon的连接超时时间
ConnectTimeout: 250
# Ribbon的数据读取超时时间
ReadTimeout: 1000
# 是否对所有操作都进行重试,需要引入spring-retry依赖
OkToRetryOnAllOperations: true
# 切换实例的重试次数
MaxAutoRetriesNextServer: 1
# 对当前实例的重试次数
MaxAutoRetries: 1
# 负载均衡方式,默认是轮询的负载均衡策略(com.netflix.loadbalancer.RoundRobinRule)
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule
添加重试机制,需要导入spring-retry依赖:
<!--负载均衡重试机制需要添加-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
然后在RestTemplate注册类上添加@LoadBalance注解,如P5所示。
Ribbon内置的7种负载均衡方式:
内置负载均衡规则类 | 规则描述 |
---|---|
com.netflix.loadbalancer.RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
com.netflix.loadbalancer.AvailabilityFilteringRule | 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。 |
com.netflix.loadbalancer.WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
com.netflix.loadbalancer.ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
com.netflix.loadbalancer.BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
com.netflix.loadbalancer.RandomRule | 随机选择一个可用的服务器。 |
com.netflix.loadbalancer.RetryRule | 重试机制的选择逻辑 |
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
ribbon:
eager-load:
enabled: true
clients: user-service
5. RestTemplate
RestTemplate主要用于RESTFUL风格的接口请求,使用HTTP协议。
使用方法,在服务消费者的主启动类中进行RestTemplate的Bean注册,如在order-service中进行注册:
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
RestTemplate Bean的主要使用方法有以下:
方法名称 | 方法用途 |
---|---|
getForObject(URI url, Class responseType) | GET方式请求,responseType为返回的类型 |
postForObject(URI url, Object request, Class responseType) | POST方式请求,request为请求体,responseType为返回的类型 |
其它的方法需要使用时进行查询。
6. Nacos
6.1 Nacos的安装
- 将软件中的nacos-server解压,进入nacos/conf/目录,打开application.properties文件
- 修改配置文件
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
- 创建数据库
CREATE DATABASE `nacos` CHARACTER SET utf8mb4;
- 执行nacos/conf/nacos-mysql.sql数据库脚本文件
- 编辑nacos/bin/startup.cmd文件,如果非集群模式,将模式改成独立运行的。
set MODE="standalone"
- 启动nacos服务,双击nacos/bin/startup.cmd
- 登录http://localhost:8848/nacos,进入nacos管理页面
6.2 服务注册到Nacos
6.2.1 引入依赖
在父工程的dependencyManagement中添加spring-cloud-alibaba依赖管理,如下所示:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
然后在服务模块的pom文件中引入nacos-discovery依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
注意:eureka的依赖要注释掉。
6.2.2 配置nacos地址
在服务模块的application.yml中添加以下配置:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 实例发送心跳的间隔时间。(单位:毫秒)
heart-beat-interval: 5000
# 该实例不发送心跳后,从健康到不健康的时间。(单位:毫秒)
heart-beat-timeout: 15000
# 该实例在不发送心跳后,被nacos下掉该实例的时间。(单位:毫秒)
ip-delete-timeout: 30000
登录nacos管理页面,可以看到微服务信息:
6.3 服务分级存储模型
一个服务可以有多个实例,例如user-service,可以有:
- 127.0.0.1:8060
- 127.0.0.1:8061
- 127.0.0.1:8062
假如这些实例分布于全国各地的不同机房,例如:
- 127.0.0.1:8060,在上海机房
- 127.0.0.1:8061,在上海机房
- 127.0.0.1:8062,在杭州机房
Nacos就将同一机房内的实例划分为一个集群。
也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:
微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:
杭州机房内的order-service应该优先访问同机房的user-service。
6.3.1 配置集群
给服务模块的application.yml中添加集群配置,如下所示:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 实例发送心跳的间隔时间。(单位:毫秒)
heart-beat-interval: 5000
# 该实例不发送心跳后,从健康到不健康的时间。(单位:毫秒)
heart-beat-timeout: 15000
# 该实例在不发送心跳后,被nacos下掉该实例的时间。(单位:毫秒)
ip-delete-timeout: 30000
# 集群名字
cluster-name: HZ
可以在nacos界面上看到服务在HZ集群下:
6.3.2 同集群优先的负载均衡
如果想要优先调用同集群下的服务,可以将负载均衡策略换成Nacos
的NacosRule
。Nacos
中提供了一个NacosRule
的实现,可以优先从同集群中挑选实例。
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
6.4 权重配置
实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。
因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。
在nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重:
权重越大,实例被访问的概率就越大。如果权重为0,实例则永远不会被访问。
6.5 环境隔离
Nacos提供了namespace来实现环境隔离功能。
- nacos中可以有多个namespace
- namespace下可以有group、service等
- 不同namespace之间相互隔离,例如不同namespace的服务互相不可见
6.5.1 创建namespace
默认情况下,所有service、data、group都在同一个namespace,名为public:
我们可以点击页面新增按钮,添加一个namespace:
然后,填写表单:
就能在页面看到一个新的namespace:
同时,在配置的nacos数据库下的tenant_info表中也可以看到新增的命名空间信息:
6.5.2 给微服务配置namespace
给微服务配置namespace只能通过修改配置来实现。
例如,修改order-service的application.yml文件:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 实例发送心跳的间隔时间。(单位:毫秒)
heart-beat-interval: 5000
# 该实例不发送心跳后,从健康到不健康的时间。(单位:毫秒)
heart-beat-timeout: 15000
# 该实例在不发送心跳后,被nacos下掉该实例的时间。(单位:毫秒)
ip-delete-timeout: 30000
# 集群名字
cluster-name: HZ
# 命名空间,填ID
namespace: d089ab10-7afd-4d02-bd2a-94eacc631ed9
不同命名空间相互隔离,服务之间无法相互访问。
6.6 Nacos与Eureka的区别
Nacos的服务实例分为两种类型:
- 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。
- 永久实例:如果实例宕机,不会从服务列表剔除。
配置一个服务实例为永久实例:
spring:
cloud:
nacos:
discovery:
ephemeral: false # 设置为非临时实例
Nacos和Eureka整体结构类似,服务注册、服务拉取、心跳等待,但是也存在一些差异:
-
Nacos与eureka的共同点
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
-
Nacos与Eureka的区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,永久实例采用主动检测模式
- 临时实例心跳不正常会被剔除,永久实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
7. 代码示例
7.1 父工程pom文件
<?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.example</groupId>
<artifactId>my-cloud-demo</artifactId>
<packaging>pom</packaging>
<version>0.0.1</version>
<name>my-cloud-demo</name>
<description>Demo project for Spring Boot</description>
<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.2.6.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<modules>
<module>order-service</module>
<module>user-service</module>
<module>eureka-server</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--spring jpa,导入这一个就行,mysql、jdbc自动依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--spring-boot版本管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring-cloud版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring-cloud-alibaba版本管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.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.example.myclouddemo.MyCloudDemoApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
7.2 Eureka示例
7.2.1 服务端服务模块pom文件
<?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>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.example</groupId>
<artifactId>my-cloud-demo</artifactId>
<version>0.0.1</version>
<relativePath>../../my-cloud-demo</relativePath>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
7.2.2 服务端服务模块application配置文件
spring:
application:
# 微服务的名称
name: eureka-server
# 微服务的端口
server:
port: 8050
eureka:
# ip地址,不配的话默认为localhost
instance:
hostname: localhost
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从eureka中获取注册信息
fetch-registry: false
# 配置暴露给Eureka Client的请求地址
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
7.2.3 服务端服务模块主启动类
package com.example.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
7.2.4 客户端服务模块pom文件
<?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.example</groupId>
<artifactId>order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>order-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<parent>
<groupId>com.example</groupId>
<artifactId>my-cloud-demo</artifactId>
<version>0.0.1</version>
<relativePath>../../my-cloud-demo</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--开启健康检测,在客户端定义-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--负载均衡重试机制需要添加-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
</project>
7.2.5 客户端服务模块application配置文件
spring:
application:
name: order-service
datasource:
url: jdbc:mysql://127.0.0.1:3306/cloud-demo?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
hibernate:
ddl-auto: update
show-sql: true
database: MYSQL
database-platform: org.hibernate.dialect.MySQL5Dialect
server:
port: 8070
eureka:
client:
service-url:
# 添加Eureka Server的主机地址
defaultZone: http://127.0.0.1:8050/eureka
instance:
# 默认服务端每隔30s向注册中心发送一次心跳,此处更改发送间隔为10s
lease-renewal-interval-in-seconds: 10
# 续约到期时间,若超过该时间注册中心未收到服务的心跳,则认为续约到期
lease-expiration-duration-in-seconds: 20
# 使用ip注册
prefer-ip-address: true
# 注册的ID使用ip
instance-id: ${spring.cloud.client.ip-address}:${server.port}
# 开启健康检查,需要引入actuator依赖
healthcheck.enabled: true
# 调用服务的名称,并设定负载均衡策略
user-service:
ribbon:
# Ribbon的连接超时时间
ConnectTimeout: 250
# Ribbon的数据读取超时时间
ReadTimeout: 1000
# 是否对所有操作都进行重试,需要引入spring-retry依赖
OkToRetryOnAllOperations: true
# 切换实例的重试次数
MaxAutoRetriesNextServer: 1
# 对当前实例的重试次数
MaxAutoRetries: 1
# 负载均衡方式,默认是轮询的负载均衡策略(com.netflix.loadbalancer.RoundRobinRule)
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
7.2.6 客户端服务模块主启动类
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
7.3 Nacos示例
7.3.1 客户端服务模块pom文件
<?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.example</groupId>
<artifactId>order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>order-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<parent>
<groupId>com.example</groupId>
<artifactId>my-cloud-demo</artifactId>
<version>0.0.1</version>
<relativePath>../../my-cloud-demo</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡重试机制需要添加-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
</project>
7.3.2 客户端服务模块application文件
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 集群名称
cluster-name: SH
# 命名空间
namespace: d089ab10-7afd-4d02-bd2a-94eacc631ed9
# 实例发送心跳的间隔时间。(单位:毫秒)
heart-beat-interval: 5000
# 该实例不发送心跳后,从健康到不健康的时间。(单位:毫秒)
heart-beat-timeout: 15000
# 该实例在不发送心跳后,被nacos下掉该实例的时间。(单位:毫秒)
ip-delete-timeout: 30000
application:
name: order-service
datasource:
url: jdbc:mysql://127.0.0.1:3306/cloud-demo?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
hibernate:
ddl-auto: update
show-sql: true
database: MYSQL
database-platform: org.hibernate.dialect.MySQL5Dialect
server:
port: 8070
# 调用服务的名称,并设定负载均衡策略
user-service:
ribbon:
# Ribbon的连接超时时间
ConnectTimeout: 250
# Ribbon的数据读取超时时间
ReadTimeout: 1000
# 是否对所有操作都进行重试,需要引入spring-retry依赖
OkToRetryOnAllOperations: true
# 切换实例的重试次数
MaxAutoRetriesNextServer: 1
# 对当前实例的重试次数
MaxAutoRetries: 1
# 负载均衡方式
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
7.3.3 客户端服务模块主启动类
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}