【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心

1、服务注册与发现

当服务很多时,单靠代码手动管理是很麻烦的,需要一个公共组件,统一管理多服务,包括服务是否正常运行等

上面只有两个微服务,通过 RestTemplate ,是可以相互调用的,但是当微服务项目的数量增大,就需要服务注册中心。目前没有学习服务调用相关技术,使用 SpringCloud 自带的 RestTemplate 来实现RPC。

1.1 什么是服务治理:

SpringCloud封装了Netflix公司开发的Eureka模块来实现服务治理

在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。

1.2 什么是服务注册与发现:

Eureka采用了CS的设计结构,Eureka Server服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。这点和zookeeper很相似

在服务注册与发现中,有一个注册中心。当服务器启动时候,会把当前自己服务器的信息 比如服务地址 通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用。RPC远程调用框架核心设计思想:在于注册中心,因为便用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))

1.3 Eureka服务注册与发现

Eureka 官方停更不停用,以后可能用的越来越少。

Eureka 是 Netflix 开发的,一个基于 REST 服务的,服务注册与发现的组件,以实现中间层服务器的负载平衡和故障转移。

Eureka 分为 Eureka Server 和 Eureka Client及服务端和客户端。Eureka Server为注册中心,是服务端,而服务提供者和消费者即为客户端,消费者也可以是服务者,服务者也可以是消费者。同时Eureka Server在启动时默认会注册自己,成为一个服务,所以Eureka Server也是一个客户端,这是搭建Eureka集群的基础。

==Eureka Client:==一个Java客户端,用于简化与 Eureka Server 的交互(通常就是微服务中的客户端和服务端)。通过注册中心进行访问。是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(roundrobin)负载算氵去的负载均衡器

在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)

==Eureka Server:==提供服务注册服务,各个微服务节,通过配置启动后,会在Eureka Serverc中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点信息,服务节点的信息可以在界面中直观看到。

服务在Eureka上注册,然后每隔30秒发送心跳来更新它们的租约。如果客户端不能多次续订租约,那么它将在大约90秒内从服务器注册表中剔除。注册信息和更新被复制到集群中的所有eureka节点。来自任何区域的客户端都可以查找注册表信息(每30秒发生一次)来定位它们的服务(可能在任何区域)并进行远程调用。

服务提供者向注册中心注册服务,并每隔30秒发送一次心跳,就如同人还活着存在的信号一样,如果Eureka在90秒后还未收到服务提供者发来的心跳时,那么它就会认定该服务已经死亡就会注销这个服务。这里注销并不是立即注销,而是会在60秒以后对在这个之间段内“死亡”的服务集中注销,如果立即注销,势必会对Eureka造成极大的负担。这些时间参数都可以人为配置。

Eureka还有自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,所以不会再接收心跳,也不会删除服务。

客户端消费者会向注册中心拉取服务列表,因为一个服务器的承载量是有限的,所以同一个服务会部署在多个服务器上,每个服务器上的服务都会去注册中心注册服务,他们会有相同的服务名称但有不同的实例id,所以拉取的是服务列表。我们最终通过负载均衡来获取一个服务,这样可以均衡各个服务器上的服务。

2、单机版eureka

  • 消费者端口80,提供者端口8001。
  • Eureka端口7001

2.1 创建module

Cloud_eureka_server_7001

2.2改pom依赖

eureka版本说明:

<!--新版本2020.02-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--旧版本2018-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

pom文件:

在这里插入代码片

2.3写yml配置文件:

server:
  port: 7001
eureka:
  instance:
    hostname: localhost  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      # 设置与 Eureka Server 交互的地址,查询服务 和 注册服务都依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

2.4主启动类

@EnableEurekaServer

最后写主启动类,如果启动报错,说没有配置 DataSource ,就在 主启动类的注解加上 这样的配置:

package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
// exclude :启动时不启用 DataSource的自动配置检查
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer   // 表示它是服务注册中心
public class EurekaServerMain7001 {
    public static void main(String[] args){
        SpringApplication.run(EurekaServerMain7001.class, args);
        log.info("EurekaServerMain7001启动成功~~~~~~~~~~~~~~~~~~~");
    }
}

启动测试,访问 7001 端口

2.5 修改服务提供者 cloud-provider-payment8001 模块,

  1. 在 pom 文件的基础上引入 eureka 的client包,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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2023</artifactId>
        <groupId>com.tigerhhzz.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>Cloud-provider-payment8001</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- 服务注册中心的客户端端 eureka-client -->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.tigerhhzz.springcloud</groupId>
            <artifactId>Cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <!--这个和web要写到一块-->
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </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>
</project>
  1. 主启动类 加上注解 :@EnableEurekaClient
package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import java.io.Console;
/**
 * @author Administrator
 */
@Slf4j
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {
    public static void main(String[] args){
        SpringApplication.run(PaymentMain8001.class, args);
        log.info("PaymentMain8001启动成功~~~~~~~~~~~~~~~~~~~");
    }
}
  1. yml 文件添加关于 Eureka 的配置:
server:
  port: 8001
spring:
  application:
    name: Cloud-provider-payment8001
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
      defaultZone: http://localhost:7001/eureka/

2.6 修改消费者 cloud-customer-order80 模块

  1. 在 pom 文件的基础上引入 eureka 的client包,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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2023</artifactId>
        <groupId>com.tigerhhzz.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>Cloud-consumer-order80</artifactId>
    <dependencies>
        <!-- 服务注册中心的客户端端 eureka-client -->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.tigerhhzz.springcloud</groupId>
            <artifactId>Cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </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>
</project>
  1. 主启动类 加上注解 :@EnableEurekaClient
package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@Slf4j
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80{
    public static void main(String[] args){
        SpringApplication.run(OrderMain80.class,args);
        log.info("OrderMain80启动成功~~~~~~~~~~~~~~~~~~~");
    }
}
  1. yml 文件添加关于 Eureka 的配置:
server:
  port: 80
spring:
  application:
    name: Cloud-consumer-order80
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka/

2.7 启动三个服务:

3、集群版eureka

3.1 集群原理

  1. 就是pay模块启动时,注册自己,并且自身信息也放入eureka
  2. order模块,首先也注册自己,放入信息,当要调用pay时,先从eureka拿到pay的调用地址
  3. 通过HttpClient调用 ,并且还会缓存一份到本地,每30秒更新一次

问题:微服务RPC远程服务调用最核心的是什么:

高可用,试想你的注册中心只有一个。onlyone,它出故障了那就呵呵了,会导致整个为服务环境不可用,所以要搭建Eureka注册中心集群,实现负载均衡+故障容错

Eureka 集群的原理:

== 相互注册,互相守望。== 每台Eureka服务器都有集群里其他Eureka服务器地址的信息

3.2 构建Eureka集群

在写配置文件前,修改一下主机的hosts文件

模拟多个 为了不用输出C:\Windows\System32\drivers\etc\hosts 添加如下:
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
  1. 创建 Cloud-eureka-server7002模块
    这也就是第二个 Eureka 服务注册中心,pom 文件和 主启动类,与第一个Cloud-eureka-server7002一致。
pom文件:
  粘贴7001的即可
<?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>springcloud2023</artifactId>
        <groupId>com.tigerhhzz.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>Cloud-eureka-server7002</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.tigerhhzz.springcloud</groupId>
            <artifactId>Cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>
配置文件:
  1. 修改7001项目的application.yml配置文件

首先修改之前的7001的eureka项目,因为多个eureka需要互相注册

7001项目的application.yml配置文件

server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com  # eureka 服务器的实例地址  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      ## 一定要注意这里的地址,这是搭建集群的关键。反过来写,写的是集群中其他Eureka服务器的地址
      defaultZone: http://eureka7002.com:7002/eureka/
  1. 修改7002项目的application.yml配置文件
7002也是一样的,只不过端口和地址改一下

7002项目的application.yml配置文件

server:
  port: 7002
eureka:
  instance:
    hostname: eureka7002.com  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      ## 一定要注意这里的地址,这是搭建集群的关键。反过来写,写的是集群中其他Eureka服务器的地址
      defaultZone: http://eureka7001.com:7001/eureka/

eureka.instance.hostname 才是启动以后 本 Server 的注册地址,而 service-url 是 map 类型,只要保证 key:value 格式就行,它代表 本Server 指向了那些 其它Server 。利用这个,就可以实现Eureka Server 相互之间的注册,从而实现集群的搭建。

  1. 主启动类:

复制7001的即可

7001主启动类:

package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
// exclude :启动时不启用 DataSource的自动配置检查
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer   // 表示它是服务注册中心
public class EurekaServerMain7001 {
    public static void main(String[] args){
        SpringApplication.run(EurekaServerMain7001.class, args);
        log.info("EurekaServerMain7001启动成功~~~~~~~~~~~~~~~~~~~");
    }
}

7002主启动类:

package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
// exclude :启动时不启用 DataSource的自动配置检查
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer   // 表示它是服务注册中心
public class EurekaServerMain7002 {
    public static void main(String[] args){
        SpringApplication.run(EurekaServerMain7002.class, args);
        log.info("EurekaServerMain7002启动成功~~~~~~~~~~~~~~~~~~~");
    }
}
  1. 然后启动7001,7002即可

3.3 将Cloud-consumer-order80,Cloud-provider-payment8001模块注册到eureka集群中

  1. 只需要修改Cloud-consumer-order80,Cloud-provider-payment8001模块的配置文件即可:

Cloud-consumer-order80配置文件

server:
  port: 80
spring:
  application:
    name: Cloud-consumer-order80
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
#      defaultZone: http://localhost:7001/eureka/   #单机版
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/   #集群版

,Cloud-provider-payment8001模块配置文件

server:
  port: 8001
spring:
  application:
    name: Cloud-provider-payment8001
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
  1. 两个模块都修改上面的都一样即可

然后启动两个模块

要先启动7001,7002,然后是pay模块8001,然后是order(80)

4、将Cloud-provider-payment模块也配置为集群模式

4.1 创建新模块Cloud-provider-payment8002

4.2 pom文件,复制8001的

Cloud-provider-payment8002模块的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2023</artifactId>
        <groupId>com.tigerhhzz.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>Cloud-provider-payment8002</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- 服务注册中心的客户端端 eureka-client -->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.tigerhhzz.springcloud</groupId>
            <artifactId>Cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <!--这个和web要写到一块-->
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </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>
</project>

4.3 配置文件复制8001的

端口修改一下,改为8002

Cloud-provider-payment8001模块的配置文件

server:
  port: 8001
spring:
  application:
#    name: Cloud-provider-payment8001
     name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版

Cloud-provider-payment8002模块的配置文件

server:
  port: 8002
spring:
  application:
#    name: Cloud-provider-payment8002
    name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版

服务名称不用改,用一样的

4.4 主启动类,复制8001的

package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
 * @author Administrator
 */
@Slf4j
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8002 {
    public static void main(String[] args){
        SpringApplication.run(PaymentMain8002.class, args);
        log.info("PaymentMain8002启动成功~~~~~~~~~~~~~~~~~~~");
    }
}

4.5 mapper,service,controller都复制一份

然后就启动服务即可

此时访问order模块,发现并没有负载均衡到两个pay,模块中,而是只访问8001

虽然我们是使用RestTemplate访问的微服务,但是也可以负载均衡的

4.6 RestTemplate开启负载均衡注解

注意这样还不可以,需要让RestTemplate开启负载均衡注解,还可以指定负载均衡算法,默认轮询

修改Cloud-consumer-order80模块中的config包下面的ApplicationContextConfig类:

package com.tigerhhzz.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
 * @author tigerhhzz
 * @date 2023/4/8 22:52
 */
@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
        /*
        RestTemplate提供了多种便捷访问远程http服务的方法,
        是一种简单便捷的访问restful服务模板类,是spring提供的用于rest服务的客户端模板工具集
        */
    }
}

4.7 修改服务主机名和ip在eureka的web上显示

actuator让Eureka显示ip

为了在微服务Eureka控制台能看到我们的某个具体服务是在哪台服务器上部署的,我们需要配置一些内容。

修改 提供者在Eureka 注册中心显示的 主机名:即修改eureka:instance:instance-id:和eureka:instance:prefer-ip-address:

修改Cloud-provider-payment8001模块的配置文件:

server:
  port: 8001
spring:
  application:
#    name: Cloud-provider-payment8001
     name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版
       
  instance: #重点,和client平行
    instance-id: payment8001 # 每个提供者的id不同,显示的不再是默认的项目名
    prefer-ip-address: true # 访问路径可以显示ip地址

修改Cloud-provider-payment8002模块的配置文件:

server:
  port: 8002
spring:
  application:
#    name: Cloud-provider-payment8002
    name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版
       
  instance: #重点,和client平行
    instance-id: payment8002 # 每个提供者的id不同,显示的不再是默认的项目名
    prefer-ip-address: true # 访问路径可以显示ip地址

5、eureka服务发现

对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息。(即我们前面可视化页面的信息)

5.1 首先添加一个注解,在controller中

package com.tigerhhzz.springcloud.controller;
import com.tigerhhzz.springcloud.entities.CommonResult;
import com.tigerhhzz.springcloud.entities.Payment;
import com.tigerhhzz.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController   //必须是这个注解,因为是模拟前后端分离的restful风格的请求,要求每个方法返回 json
@Slf4j
public class PaymentController {
  @Resource
  private PaymentService paymentService;
    //服务发现
    @Resource
    private DiscoveryClient discoveryClient;
    @Value("${server.port}")
    private String serverPort;
  @PostMapping(value = "/payment/create")
  //      注意这里的 @RequestBody  是必须要写的,虽然 MVC可以自动封装参数成为对象,
  //      但是当消费者项目调用,它传参是 payment 整个实例对象传过来的, 即Json数据,因此需要写这个注解
  //
  public CommonResult create(@RequestBody Payment payment){
      int result = paymentService.create(payment);
      log.info("****插入结果:" + result);
      if(result > 0){
          return new CommonResult(200, "插入数据库成功", result);
      }
      return new CommonResult(400, "插入数据库失败", null);
  }
  @GetMapping(value = "/payment/{id}")
  public CommonResult getPaymentById(@PathVariable("id")Long id){
      Payment result = paymentService.getPaymentById(id);
      log.info("****查询结果:" + result);
      if(result != null){
          return new CommonResult(200, "查询成功", result);
      }
      return new CommonResult(400, "没有对应id的记录", null);
  }
    @GetMapping("queryAllByLimit")
    public CommonResult<List<Payment>> queryAllByLimit(@RequestParam(defaultValue = "0") int offset,
                                                       @RequestParam(defaultValue = "10") int limit) {
        List<Payment> payment = this.paymentService.queryAllByLimit(offset, limit);
        return new CommonResult<>(200, "select success, serverPort:" + serverPort, payment);
    }
    @GetMapping("/customer/discovery")
    public Object discovery(){
        //获得服务清单列表
        List<String> services = discoveryClient.getServices();
        for(String service: services){
            log.info("*****service: " + service);
        }
        // 根据具体服务进一步获得该微服务的信息
        List<ServiceInstance> instances = discoveryClient.getInstances("cloud-provider-service");
        for(ServiceInstance serviceInstance:instances){
            log.info(serviceInstance.getServiceId() + "\t" + serviceInstance.getHost()
                    + "\t" + serviceInstance.getPort() + "\t" + serviceInstance.getUri());
        }
        return this.discoveryClient;
    }
}

5.2 在主启动类上添加一个注解

  • 在主启动类上添加注解:@EnableDiscoveryClient
package com.tigerhhzz.springcloud;
import lombok.extern.slf4j.Slf4j;
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;
import java.io.Console;
/**
 * @author Administrator
 */
@Slf4j
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {
    public static void main(String[] args){
        SpringApplication.run(PaymentMain8001.class, args);
        log.info("PaymentMain8001启动成功~~~~~~~~~~~~~~~~~~~");
    }
}

打印输出:

6、Eureka自我保护

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

禁止自我保护:(如果想)

6.1 在 Eureka Server 的模块中的 yml 文件进行配置:

Cloud-eureka-server7001配置文件:

server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com  # eureka 服务器的实例地址  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      ## 一定要注意这里的地址,这是搭建集群的关键。反过来写,写的是集群中其他Eureka服务器的地址
      defaultZone: http://eureka7002.com:7002/eureka/
  server: # 与client平行
    # 关闭自我保护机制,保证不可用该服务被及时剔除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000

Cloud-eureka-server7002配置文件:

server:
  port: 7002
eureka:
  instance:
    hostname: eureka7002.com  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      ## 一定要注意这里的地址,这是搭建集群的关键。反过来写,写的是集群中其他Eureka服务器的地址
      defaultZone: http://eureka7001.com:7001/eureka/
  server: # 与client平行
    # 关闭自我保护机制,保证不可用该服务被及时剔除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000

6.2 服务提供者配置

修改 Eureka Client —Cloud-provider-payment8001模块的 心跳间隔时间:

server:
  port: 8001
spring:
  application:
#    name: Cloud-provider-payment8001
     name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版
  instance: #重点,和client平行
    instance-id: payment8001 # 每个提供者的id不同,显示的不再是默认的项目名
    prefer-ip-address: true # 访问路径可以显示ip地址
    # Eureka客户端像服务端发送心跳的时间间隔,单位s,默认30s
    least-renewal-interval-in-seconds: 1
    # Rureka服务端在收到最后一次心跳后等待时间上线,单位为s,默认90s,超时将剔除服务
    least-expiration-duration-in-seconds: 2

修改 Eureka Client —Cloud-provider-payment8002模块的 心跳间隔时间:

server:
  port: 8002
spring:
  application:
#    name: Cloud-provider-payment8002
    name: cloud-provider-service  # 这次重点是这里,两个要写的一样,这是这个集群的关键
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud-tigerhhzz?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tigerhhzz.springcloud.entities  # 所有Entity 别名类所在包
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
#      defaultZone: http://localhost:7001/eureka/  #单机版
       defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/ #集群版
  instance: #重点,和client平行
    instance-id: payment8002 # 每个提供者的id不同,显示的不再是默认的项目名
    prefer-ip-address: true # 访问路径可以显示ip地址
    # Eureka客户端像服务端发送心跳的时间间隔,单位s,默认30s
    least-renewal-interval-in-seconds: 1
    # Rureka服务端在收到最后一次心跳后等待时间上线,单位为s,默认90s,超时将剔除服务
    least-expiration-duration-in-seconds: 2

6.3 eureka配置项

在注册服务之后,服务提供者会维护一个心跳用来持续高速Eureka Server,“我还在持续提供服务”,否则Eureka Server的剔除任务会将该服务实例从服务列表中排除出去。我们称之为服务续约。

面是服务续约的两个重要属性:

(1)eureka.instance.lease-expiration-duration-in-seconds

leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance。

默认为90秒

如果该值太大,则很可能将流量转发过去的时候,该instance已经不存活了。

如果该值设置太小了,则instance则很可能因为临时的网络抖动而被摘除掉。

该值至少应该大于leaseRenewalIntervalInSeconds

(2)eureka.instance.lease-renewal-interval-in-seconds

  • leaseRenewalIntervalInSeconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外,如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量。
    默认30秒
  • eureka.client.registry-fetch-interval-seconds :表示eureka client间隔多久去拉取服务注册信息,默认为30秒,对于api-gateway,如果要迅速获取服务注册状态,可以缩小该值,比如5秒
  • eureka.server.enable-self-preservation
    是否开启自我保护模式,默认为true。

默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。

Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

eureka.server.eviction-interval-timer-in-ms

eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒

Eureka停更说明:2.0后停更了。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1天前
|
Cloud Native Java 关系型数据库
【阿里云云原生专栏】构建云原生应用:基于Spring Boot与阿里云服务的全栈指南
【5月更文挑战第21天】构建云原生应用是企业数字化转型的关键,本文提供了一份基于Spring Boot和阿里云的全栈指南。涵盖从阿里云账号注册、ECS与Docker搭建,到Spring Boot项目创建、业务代码编写和部署。此外,还介绍了如何集成阿里云OSS存储、RDS数据库服务以及ACK容器服务,助力打造高效、可扩展和易管理的云原生应用。
101 3
|
6天前
|
负载均衡 监控 算法
【微服务 SpringCloud】实用篇 · Eureka注册中心
【微服务 SpringCloud】实用篇 · Eureka注册中心
21 1
|
6天前
|
Java Docker 微服务
|
6天前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
|
6天前
|
缓存 负载均衡 监控
SpringCloud&Eureka理论与入门
SpringCloud&Eureka理论与入门
22 0
|
6天前
|
负载均衡 监控 容灾
【SpringCloud】详解Eureka注册中心
【SpringCloud】详解Eureka注册中心
25 0
|
6天前
|
Java Maven 微服务
第四章 Spring Cloud Netflix 之 Eureka
第四章 Spring Cloud Netflix 之 Eureka
15 0
|
6天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
6天前
|
Java API 微服务
【Spring Boot系列】通过OpenAPI规范构建微服务服务接口
【4月更文挑战第5天】通过OpenAPI接口构建Spring Boot服务RestAPI接口
64 0
|
6天前
|
Java 微服务 Spring
Spring Cloud Eureka详细介绍
Spring Cloud Eureka详细介绍
24 1