SpringCloud之Eureka、Ribbon及Nacos

SpringCloud之Eureka、Ribbon及Nacos

1. 单体架构和微服务架构

单体架构: 将业务的所有功能集中在一个项目中开发,打成一个包部署。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mY5sgD1Q-1681126839487)(C:\Users\YoungDk\AppData\Roaming\Typora\typora-user-images\image-20230407163916066.png)]
单体架构的优缺点:

优点:

  • 架构简单
  • 部署成本低

缺点:

  • 模块之间的耦合程度高,维护困难,功能升级困难

微服务架构: 根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,作为一个服务。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mbXygcP9-1681126839488)(C:\Users\YoungDk\AppData\Roaming\Typora\typora-user-images\image-20230407164152741.png)]
微服务架构的优缺点:

优点:

  • 服务之间的耦合程度降低
  • 有利于服务升级与扩展

缺点:

  • 服务调用关系错综复杂

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 VersionSpring Cloud VersionSpring Boot Version
2022.0.0.0-RC*Spring Cloud 2022.0.03.0.0
2021.x 分支

适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2021.0.4.0*Spring Cloud 2021.0.42.6.11
2021.0.1.0Spring Cloud 2021.0.12.6.3
2021.1Spring Cloud 2020.0.12.4.2
2.2.x 分支

适配 Spring Boot 为 2.4,Spring Cloud Hoxton 版本及以下的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2.2.10-RC1*Hoxton.SR122.3.12.RELEASE
2.2.9.RELEASEHoxton.SR122.3.12.RELEASE
2.2.8.RELEASEHoxton.SR122.3.12.RELEASE
2.2.7.RELEASEHoxton.SR122.3.12.RELEASE
2.2.6.RELEASEHoxton.SR92.3.2.RELEASE
2.2.1.RELEASEHoxton.SR32.2.5.RELEASE
2.2.0.RELEASEHoxton.RELEASE2.2.X.RELEASE
2.1.4.RELEASEGreenwich.SR62.1.13.RELEASE
2.1.2.RELEASEGreenwich2.1.X.RELEASE
2.0.4.RELEASE(停止维护,建议升级)Finchley2.0.X.RELEASE
1.5.1.RELEASE(停止维护,建议升级)Edgware1.5.X.RELEASE
组件版本关系

每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示(注意,Spring Cloud Dubbo 从 2021.0.1.0 起已被移除出主干,不再随主干演进):

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version
2.2.10-RC11.8.62.2.04.9.4~1.6.1
2022.0.0.0-RC11.8.62.2.1-RC4.9.4~1.6.1
2.2.9.RELEASE1.8.52.1.04.9.4~1.5.2
2021.0.4.01.8.52.0.44.9.4~1.5.2
2.2.8.RELEASE1.8.42.1.04.9.3~1.5.1
2021.0.1.01.8.31.4.24.9.2~1.4.2
2.2.7.RELEASE1.8.12.0.34.6.12.7.131.3.0
2.2.6.RELEASE1.8.11.4.24.4.02.7.81.3.0
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE1.8.01.4.14.4.02.7.81.3.0
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE1.8.01.3.34.4.02.7.81.3.0
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE1.7.11.2.14.4.02.7.61.2.0
2.2.0.RELEASE1.7.11.1.44.4.02.7.4.11.0.0
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE1.7.01.1.44.4.02.7.30.9.0
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE1.6.31.1.14.4.02.7.30.7.1

最早使用SpringCloud版本的时候,直接将查找出来的版本当作version放在dependency中,导致maven导包的时候一直报包找不到的错误,后经查阅发现SpringCloud Version是要放在dependencyManagement中进行统一管理的。

最佳使用方式:
先创建一个父工程,并在父工程的pom中将<packaging>改成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页面上显示如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZpH2f1bI-1681126839489)(C:\Users\YoungDk\AppData\Roaming\Typora\typora-user-images\image-20230407174429601.png)]

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的安装
  1. 将软件中的nacos-server解压,进入nacos/conf/目录,打开application.properties文件
  2. 修改配置文件
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
  1. 创建数据库
CREATE DATABASE `nacos` CHARACTER SET utf8mb4;
  1. 执行nacos/conf/nacos-mysql.sql数据库脚本文件
  2. 编辑nacos/bin/startup.cmd文件,如果非集群模式,将模式改成独立运行的。
set MODE="standalone"
  1. 启动nacos服务,双击nacos/bin/startup.cmd
  2. 登录http://localhost:8848/nacos,进入nacos管理页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIsM50OI-1681126839489)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410160134231.png)]

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管理页面,可以看到微服务信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ey5MwZqq-1681126839489)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410160304234.png)]

注意:一定要在web的环境下服务注册才能成功,否则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是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXnihfy9-1681126839489)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210713232522531.png)]
微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SjVnroXy-1681126839490)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210713232658928.png)]

杭州机房内的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集群下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWCq24rs-1681126839490)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410161830537.png)]

6.3.2 同集群优先的负载均衡

如果想要优先调用同集群下的服务,可以将负载均衡策略换成NacosNacosRuleNacos中提供了一个NacosRule的实现,可以优先从同集群中挑选实例。

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
6.4 权重配置

实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。
因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。
在nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxGgtG7m-1681126839490)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410162631821.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQq8VyoD-1681126839490)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410162701143.png)]

权重越大,实例被访问的概率就越大。如果权重为0,实例则永远不会被访问。

6.5 环境隔离

Nacos提供了namespace来实现环境隔离功能。

  • nacos中可以有多个namespace
  • namespace下可以有group、service等
  • 不同namespace之间相互隔离,例如不同namespace的服务互相不可见

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y2zJ5e6R-1681126839491)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714000101516.png)]

6.5.1 创建namespace

默认情况下,所有service、data、group都在同一个namespace,名为public:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9AZGsut0-1681126839491)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714000414781.png)]

我们可以点击页面新增按钮,添加一个namespace:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UK0o4aav-1681126839491)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714000440143.png)]

然后,填写表单:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M91MTp29-1681126839491)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714000505928.png)]

就能在页面看到一个新的namespace:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Duf1K3ck-1681126839492)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714000522913.png)]

同时,在配置的nacos数据库下的tenant_info表中也可以看到新增的命名空间信息:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9vK6EWcV-1681126839492)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20230410164726841.png)]

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整体结构类似,服务注册、服务拉取、心跳等待,但是也存在一些差异:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yC23azEW-1681126839492)(SpringCloud之Eureka、Ribbon及Nacos.assets/image-20210714001728017.png)]

  • 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: com.example.jpa_test.cfg.DefaultMySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
    show-sql: true
    database: MYSQL
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
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

自定义一个类DefaultMySQL5InnoDBDialect,如下所示:

package com.example.jpa_test.cfg;

import org.hibernate.dialect.MySQL5Dialect;

public class DefaultMySQL5InnoDBDialect extends MySQL5Dialect {

    @Override
    public String getTableTypeString() {
        return "ENGINE=INNODB DEFAULT CHARSET=utf8mb4";
    }
}
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();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值