Eureka服务注册与发现

文章目录

  • Eureka基础知识
  • Eureka配置项
    • Eureka Server 配置项
    • Eureka client配置项
    • 服务实例配置项(eureka.instance.*)
    • Eureka Server 集群配置(eureka.server.*)
  • 单机Eureka构建步骤
    • Eureka Server服务注册中心
      • 新建Module:cloud-eureka-server7001
      • 2、引入pom依赖
      • 3、创建application.yml配置文件
      • 4、主启动类上加注解 @EnableEurekaServer
      • 测试访问 http://localhost:7001
    • Eureka client客户端
      • 1.新建模块cloud-provider-payment8001
      • 2、在cloud-provider-payment8001服务中引入依赖
      • 3、application.yml配置文件
      • 4、主启动类加注解@EnableEurekaClient
      • 5、测试
  • 集群Eureka搭建步骤
    • Eureka Server集群
      • 1.新建cloud-eureka-server7002微服务
      • 2、引入pom依赖
      • 3、修改映射配置
      • 4、修改7001和7002的application.yml配置
      • 5、测试微服务是否注册成功
  • Servce provider 服务的提供者
    • 1. 新建cloud-provider-payment8001微服务
    • 2. 引入pom依赖
    • 3.application.yml配置:
    • 4 .主启动动类上添加@EnableEurekaClient注解
    • 5.新建相关业务类
      • mapper接口
      • mapper.xml
      • service接口
      • service接口实现类
      • Controller
    • 6. 测试
  • Servce consumer 服务消费者
    • 1.新建 cloud-consumer-order80微服务**
    • 2、引入pom依赖:
    • 3、application.yml配置
    • 4、创建负载均衡配置类
    • 5、主启动上添加@EnableEurekaClient
    • 6、编写controller
    • 7、测试调用服务提供者
    • 8、验证下服务是否能被消费
  • Eureka的自我保护机制
    • 为什么会出现自我保护机制?
    • 怎么禁止Eureka的自我保护?
      • 1.在Eureka Service7001关闭自我保护机制
      • 2. Eureka client8001
      • 测试服务

Eureka基础知识

什么是服务治理?

Spring Cloud 封装了Netflix公司开发的Eureka来实现服务治理

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

什么是服务注册?

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

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

Eureka服务注册与发现_第1张图片
Eureka三大角色

Eureka Server:提供服务的注册与发现,类似Zookeeper
Service Provider:将自服务注册到Eureka中,从而使消费方能够找到
Service Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务

Eureka两大组件:Eureka Server和Eureka Client

Eureka Server提供服务注册服务

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

EurekaClient通过注册中心进行访问

是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

Spring cloud聚合父工程project添加链接描述

Eureka配置项

Eureka Server 配置项

参数名称 说明 默认值
eureka.server.enable-self-preservation 启用自我保护机制 true
eureka.server.eviction-interval-timer-in-ms 清除无效服务实例的时间间隔(ms) 60000
eureka.server.delta-retention-timer-interval-in-ms 清理无效增量信息的时间间隔(ms) 30000
eureka.server.disable-delta 禁用增量获取服务实例信息 false
eureka.server.log-identity-headers 是否记录登录日志 true
eureka.server.rate-limiter-burst-size 限流大小 10
eureka.server.rate-limiter-enabled 是否启用限流 false
eureka.server.rate-limiter-full-fetch-average-rate 平均请求速率 100
eureka.server.rate-limiter-throttle-standard-clients 是否对标准客户端进行限流 false
eureka.server.rate-limiter-registry-fetch-average-rate 服务注册与拉取的平均速率 500
eureka.server.rate-limiter-privileged-clients 信任的客户端列表
eureka.server.renewal-percent-threshold 15分钟内续约服务的比例小于0.85,则开启自我保护机制,再此期间不会清除已注册的任何服务(即便是无效服务) 0.85
eureka.server.renewal-threshold-update-interval-ms 更新续约阈值的间隔(分钟) 15
eureka.server.response-cache-auto-expiration-in-seconds 注册信息缓存有效时长(s) 180
eureka.server.response-cache-auto-expiration-in-seconds 注册信息缓存更新间隔(s) 30
eureka.server.retention-time-in-m-s-in-delta-queue 保留增量信息时长(分钟) 3
eureka.server.sync-when-timestamp-differs 当时间戳不一致时,是否进行同步 true
eureka.server.use-read-only-response-cache 是否使用只读缓存策略 true

Eureka client配置项

参数名称 说明 默认值
eureka.client.enabled 用于指示Eureka客户端已启用的标志 true
eureka.client.registry-fetch-interval-seconds 指示从eureka服务器获取注册表信息的频率(s) 30s
eureka.client.instance-info-replication-interval-seconds 更新实例信息的变化到Eureka服务端的间隔时间(s) 30s
eureka.client.initial-instance-info-replication-interval-seconds 初始化实例信息到Eureka服务端的间隔时间(s) 40s
eureka.client.eureka-service-url-poll-interval-seconds 询问Eureka Server信息变化的时间间隔(s) 300s
eureka.client.eureka-server-read-timeout-seconds 读取Eureka Server 超时时间(s) 8s
eureka.client.eureka-server-connect-timeout-seconds 连接Eureka Server 超时时间(s) 5s
eureka.client.eureka-server-total-connections 获取从eureka客户端到所有eureka服务器的连接总数 200个
eureka.client.eureka-server-total-connections-per-host 获取从eureka客户端到eureka服务器主机允许的连接总数 50个
eureka.client.eureka-connection-idle-timeout-seconds 连接到 Eureka Server 空闲连接的超时时间(s) 30
eureka.client.registry-refresh-single-vip-address 指示客户端是否仅对单个VIP的注册表信息感兴趣 null
eureka.client.heartbeat-executor-thread-pool-size 心跳保持线程池初始化线程数 2个
eureka.client.heartbeat-executor-exponential-back-off-bound 心跳超时重试延迟时间的最大乘数值 10
eureka.client.serviceUrl.defaultZone 可用区域映射到与eureka服务器通信的完全限定URL列表。每个值可以是单个URL或逗号分隔的备用位置列表。
eureka.client.use-dns-for-fetching-service-urls 指示eureka客户端是否应使用DNS机制来获取要与之通信的eureka服务器列表。当DNS名称更新为具有其他服务器时,eureka客户端轮询eurekaServiceUrlPollIntervalSeconds中指定的信息后立即使用该信息。
eureka.client.register-with-eureka 指示此实例是否应将其信息注册到eureka服务器以供其他服务发现 true
eureka.client.fetch-registry 指示此实例是否从eureka中获取注册信息 true
eureka.client.prefer-same-zone-eureka 实例是否使用同一zone里的eureka服务器,理想状态下,eureka客户端与服务端是在同一zone下 true
eureka.client.log-delta-diff 是否记录eureka服务器和客户端之间在注册表的信息方面的差异 false
eureka.client.disable-delta 指示eureka客户端是否禁用增量提取 false
eureka.client.fetch-remote-regions-registry 逗号分隔的区域列表,提取eureka注册表信息
eureka.client.on-demand-update-status-change 客户端的状态更新到远程服务器上 true
eureka.client.allow-redirects 指示服务器是否可以将客户端请求重定向到备份服务器/集群。如果设置为false,则服务器将直接处理请求。如果设置为true,则可以将HTTP重定向发送到具有新服务器位置的客户端。 false
eureka.client.availability-zones.* 获取此实例所在区域的可用区域列表(在AWS数据中心中使用)。更改在运行时在registryFetchIntervalSeconds指定的下一个注册表获取周期生效。
eureka.client.backup-registry-impl 获取实现BackupRegistry的实现的名称,该实现仅在eureka客户端启动时第一次作为后备选项获取注册表信息。 对于需要额外的注册表信息弹性的应用程序,可能需要这样做,否则它将无法运行。
eureka.client.cache-refresh-executor-exponential-back-off-bound 在发生一系列超时的情况下,它是重试延迟的最大乘数值。 10
eureka.client.cache-refresh-executor-thread-pool-size 缓存刷新线程池初始化线程数量 2
eureka.client.client-data-accept 客户端数据接收的名称 full
eureka.client.decoder-name 解码器名称
eureka.client.dollar-replacement eureka 服务器序列化/反序列化的信息中获取“$”符号的替换字符串。 默认为“_-”
eureka.client.encoder-name 编码器名称
eureka.client.escape-char-replacement eureka 服务器序列化/反序列化的信息中获取“_”符号的的替换字符串。 默认为“__“
eureka.client.eureka-server-d-n-s-name 获取要查询的DNS名称来获得eureka服务器,此配置只有在eureka服务器ip地址列表是在DNS中才会用到 null
eureka.client.eureka-server-port 获取eureka服务器的端口,此配置只有在eureka服务器ip地址列表是在DNS中才会用到 null
eureka.client.eureka-server-u-r-l-context 表示eureka注册中心的路径,如果配置为eureka,则为http://ip:port/eureka/,在eureka的配置文件中加入此配置表示eureka作为客户端向注册中心注册,从而构成eureka集群。此配置只有在eureka服务器ip地址列表是在DNS中才会用到 null
eureka.client.filter-only-up-instances 是否过滤掉非up实例 true
eureka.client.g-zip-content 当服务端支持压缩的情况下,是否支持从服务端获取的信息进行压缩 true
eureka.client.property-resolver 属性解析器
eureka.client.proxy-host 获取eureka server 的代理主机名 null
eureka.client.proxy-password 获取eureka server 的代理主机密码 null
eureka.client.proxy-port 获取eureka server 的代理主机端口 null
eureka.client.proxy-user-name 获取eureka server 的代理用户名 null
eureka.client.region 获取此实例所在的区域(在AWS数据中心中使用)。 us-east-1
eureka.client.should-enforce-registration-at-init client 在初始化阶段是否强行注册到注册中心 false
eureka.client.should-unregister-on-shutdown client 在shutdown情况下,是否显示从注册中心注销 true

服务实例配置项(eureka.instance.*)

参数名称 说明 默认值
eureka.instance.appname 注册到注册中心的应用名称 unknown
eureka.instance.a-s-g-name 注册到注册中心的应用所属分组名称(AWS服务器) null
eureka.instance.app-group-name 注册到注册中心的应用所属分组名称 null
eureka.instance.data-center-info 指定服务实例所属数据中心
eureka.instance.instance-enabled-onit 指示是否应在eureka注册后立即启用实例以获取流量 false
eureka.instance.non-secure-port http通信端口 80
eureka.instance.non-secure-port-enabled 是否启用HTTP通信端口 true
eureka.instance.secure-port HTTPS通信端口 443
eureka.instance.secure-port-enabled 是否启用HTTPS通信端口 false
eureka.instance.secure-virtual-host-name 服务实例安全主机名称(HTTPS) unknown
eureka.instance.virtual-host-name 该服务实例非安全注解名称(HTTP) unknown
eureka.instance.secure-health-check-url 该服务实例安全健康检查地址(URL) 绝对地址
eureka.instance.lease-renewal-interval-in-seconds 该服务实例向注册中心发送心跳间隔(s) 30
eureka.instance.lease-expiration-duration-in-seconds 指示eureka服务器在删除此实例之前收到最后一次心跳之后等待的时间(s) 90
eureka.instance.metadata-map.* 自定义元数据,符合KEY/VALUE的存储格式。这 些元数据可以在远程客户端中访问。
eureka.instance.ip-address 该服务实例的IP地址 null
eureka.instance.prefer-ip-address 是否优先使用服务实例的IP地址,相较于hostname false
eureka.instance.status-page-url 该服务实例的状态检查地址(url),绝对地址 null
eureka.instance.status-page-url-path 该服务实例的状态检查地址,相对地址 /actuator/info
eureka.instance.home-page-url 该服务实例的主页地址(url),绝对地址
eureka.instance.home-page-url-path 该服务实例的主页地址,相对地址 /
eureka.instance.health-check-url 该服务实例的健康检查地址(url),绝对地址 null
eureka.instance.health-check-url-path 该服务实例的健康检查地址,相对地址 /actuator/health
eureka.instance.instance-id 该服务实例在注册中心的唯一实例ID
eureka.instance.hostname 该服务实例所在主机名
eureka.instance.namespace 获取用于查找属性的命名空间。 在Spring Cloud中被忽略。 eureka
eureka.instance.environment 该服务实例环境配置
eureka.instance.default-address-resolution-order 默认地址解析顺序
eureka.instance.initial-status 该服务实例注册到Eureka Server 的初始状态 up
eureka.instance.registry.default-open-for-traffic-count 【Eureka Server 端属性】默认开启通信的数量 1
eureka.instance.registry.expected-number-of-renews-per-min 【Eureka Server 端属性】每分钟续约次数 1

Eureka Server 集群配置(eureka.server.*)

参数 说明 默认值
eureka.server.enable-replicated-request-compression 复制数据请求时,数据是否压缩 false
eureka.server.batch-replication 节点之间数据复制是否采用批处理 false
eureka.server.max-elements-in-peer-replication-pool 备份池最大备份事件数量 1000
eureka.server.max-elements-in-status-replication-pool 状态备份池最大备份事件数量 1000
eureka.server.max-idle-thread-age-in-minutes-for-peer-replication 节点之间信息同步线程最大空闲时间(分钟) 15
eureka.server.max-idle-thread-age-in-minutes-for-peer-replication 节点之间状态同步线程最大空闲时间(分钟) 10
eureka.server.max-threads-for-peer-replication 节点之间信息同步最大线程数量 20
eureka.server.max-threads-for-status-replication 节点之间状态同步最大线程数量 1
eureka.server.max-time-for-replication 节点之间信息复制最大通信时长(ms) 3000
eureka.server.min-available-instances-for-peer-replication 集群中服务实例最小数量,-1 表示单节点 -1
eureka.server.min-threads-for-peer-replication 节点之间信息复制最小线程数量 5
eureka.server.min-threads-for-status-replication 节点之间信息状态同步最小线程数量 1
eureka.server.number-of-replication-retries 节点之间数据复制时,可重试次数 5
eureka.server.peer-eureka-nodes-update-interval-ms 节点更新数据间隔时长(分钟) 10
eureka.server.peer-eureka-status-refresh-time-interval-ms 节点之间状态刷新间隔时长(ms) 30000
eureka.server.peer-node-connect-timeout-ms 节点之间连接超时时长(ms) 200
eureka.server.peer-node-connection-idle-timeout-seconds 节点之间连接后,空闲时长(s) 30
eureka.server.peer-node-read-timeout-ms 几点之间数据读取超时时间(ms) 200
eureka.server.peer-node-total-connections 集群中节点连接总数 1000
eureka.server.peer-node-total-connections-per-host 节点之间连接,单机最大连接数量 500
eureka.server.registry-sync-retries 节点启动时,尝试获取注册信息的次数 500
eureka.server.registry-sync-retry-wait-ms 节点启动时,尝试获取注册信息的间隔时长(ms) 30000
eureka.server.wait-time-in-ms-when-sync-empty 在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间(分钟) 5

单机Eureka构建步骤

Eureka Server服务注册中心

新建Module:cloud-eureka-server7001

Eureka服务注册与发现_第2张图片

2、引入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>cloud2024</artifactId>
        <groupId>com.my.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>

    <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <!--boot web actuator-->
        <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>
        <!--一devtools热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
</project>

3、创建application.yml配置文件

spring:
  application:
    name: Eureka-Service7001

server:
  port: 7001

eureka:
  client:
    register-with-eureka: true     #false表示不向注册中心注册自己。
    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
    #单机就是7001自己
      defaultZone: http://eureka7001.com:7001/eureka/
      #集群指向其它eureka
      #defaultZone: http://eureka7002.com:7002/eureka/
  instance:
    #向注册中心注册服务ID
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true     #显示IP地址
  server:
    #Eureka自我保护机制,(默认是开启的)
    enable-self-preservation: true
    # 设置心跳时间(eureka默认心跳时间是30秒)
    eviction-interval-timer-in-ms: 30000

4、主启动类上加注解 @EnableEurekaServer

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer  //eureka server 注册中心
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}

测试访问 http://localhost:7001

Eureka服务注册与发现_第3张图片

到这里服务注册中心就基本搭建完成了,现在我们需要将其他模块中的服务注册进来

Eureka client客户端

cloud-provider-payment8001将注册进EurekaServer成为服务提供者provider

1.新建模块cloud-provider-payment8001

Eureka服务注册与发现_第4张图片

2、在cloud-provider-payment8001服务中引入依赖

 <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

3、application.yml配置文件

server:
  port: 8001
spring:
  application:
    name: cloud-payment-service

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: payment8001
    prefer-ip-address: true #访问路径可以显示IP地址


4、主启动类加注解@EnableEurekaClient

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;

/**
 *
 */
@SpringBootApplication
@EnableEurekaClient//代表Eureka客户端
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }
}

5、测试

先要启动EurekaServer,然后启动cloud-provider-payment8001模块,最后访问http://localhost:7001/
Eureka服务注册与发现_第5张图片

集群Eureka搭建步骤

微服务RPC远程服务调用最核心的是什么?

高可用,试想你的注册中心只有一个only one, 它出故障了那就呵呵了,会导致整个为服务环境不可用。

解决办法:搭建Eureka注册中心集群 ,实现负载均衡+故障容错

集群实现方式:多台Eureka Server互相注册

Eureka集群原理说明

Eureka服务注册与发现_第6张图片

Eureka Server集群

注册中心这么关键的服务,如果是单点话,遇到故障就是毁灭性的。在一个分布式系统中,服务注册中心是最重要的基础部分,理应随时处于可以提供服务的状态。为了维持其可用性,使用集群是很好的解决方案。Eureka通过互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用的serviceUrl就能实现高可用部署。

在生产中我们可能需要三台或者大于三台的注册中心来保证服务的稳定性,配置的原理其实都一样,将注册中心分别指向其它的注册中心。这里只介绍三台集群的配置情况,其实和双节点的注册中心类似,每台注册中心分别又指向其它两个节点即可,使用application.yml来配置。

Eureka Server 集群环境构建步骤

参考cloud-eureka-server7001微服务

1.新建cloud-eureka-server7002微服务

2、引入pom依赖

<!--eureka-server-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

3、修改映射配置

找到C:\Windows\System32\drivers\etc路径下的hosts文件,添加如下配置

Eureka服务注册与发现_第7张图片不添加这个使用端口号访问的方式也是可以的,做这个由于咱是在一台机器上面模拟的

4、修改7001和7002的application.yml配置

7001:

spring:
  application:
    name: Eureka-Service7001

server:
  port: 7001

eureka:
  client:
    register-with-eureka: false   #false表示不向注册中心注册自己
    fetch-registry: false  #false表示自己就是注册中心,我的职责就是维护服务实例,不需要去检索服务
    service-url:
    #单机就是7001自己
      #defaultZone: http://eureka7001.com:7001/eureka/
      #集群指向其它eureka
      defaultZone: http://eureka7002.com:7002/eureka/
  instance:
    #向注册中心注册服务ID
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true     #显示IP地址
  server:
    #Eureka自我保护机制,(默认是开启的)
    enable-self-preservation: true
    # 清除无效服务实例的时间间隔(默认60000 ms)
    eviction-interval-timer-in-ms: 60000

7002:

spring:
  application:
    name: Eureka-Service7002
server:
  port: 7002

eureka:
  client:
    register-with-eureka: true     #false表示不向注册中心注册自己。
    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      #单机就是7002自己
    #defaultZone: http://eureka7002.com:7002/eureka/
      #集群指向其它eureka
      defaultZone: http://eureka7001.com:7001/eureka/
  instance:
    #向注册中心注册服务ID
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true     #显示IP地址
  server:
    #Eureka自我保护机制,(默认是开启的)
    enable-self-preservation: true
    # 清除无效服务实例的时间间隔(默认60000 ms)
    eviction-interval-timer-in-ms: 60000

5、测试微服务是否注册成功

集群搭建好之后,查看这两台注册中心是否已经户向注册

Eureka服务注册与发现_第8张图片
可以看到,两台节点互相注册成功,一般集群最少也要搭建三个节点,这里为了方便就两个

Servce provider 服务的提供者

服务的提供者,将服务注册到Eureka当中

1. 新建cloud-provider-payment8001微服务

Eureka服务注册与发现_第9张图片

2. 引入pom依赖

<!--eureka-client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

3.application.yml配置:

server:
  # 服务器的HTTP端口
  port: 8001

# Spring配置
spring:
  application:
    name: cloud-payment-service   #微服务名称

#配置数据源
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driverClassName: com.mysql.cj.jdbc.Driver              # mysql驱动包 com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2024?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: 123456

#eureka配置
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #defaultZone: http://localhost:7001/eureka # 单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
  instance:
    #向注册中心注册服务ID
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true #访问路径可以显示IP地址
    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30)
    lease-renewal-interval-in-seconds: 30
    #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90),超时将剔除服务
    lease-expiration-duration-in-seconds: 90

#mybatis配置
mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.my.springcloud.entities    # 所有Entity别名类所在包

4 .主启动动类上添加@EnableEurekaClient注解

package com.my.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


@SpringBootApplication
@EnableEurekaClient //服务的提供者,将服务注册到Eureka当中
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }
}

5.新建相关业务类

mapper接口

import com.my.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface PaymentDao {
    public int create(Payment payment);
    public Payment getPaymentById(@Param("id") Long id);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.my.springcloud.dao.PaymentDao">
   
    <resultMap id="BaseResultMap" type="com.my.springcloud.entities.Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    </resultMap>
    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select *
        from payment
        where id = #{id};
    </select>
    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)
        values (#{serial});
    </insert>
</mapper>

service接口

import com.my.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
public interface PaymentService {
    public int create(Payment payment);
    public Payment getPaymentById(@Param("id") Long id);
}

service接口实现类

import com.my.springcloud.dao.PaymentDao;
import com.my.springcloud.entities.Payment;
import com.my.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Resource
    private PaymentDao paymentDao;
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}

Controller


import com.my.springcloud.utils.RestResponse;
import com.my.springcloud.entities.Payment;
import com.my.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;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverPort;
   
     @GetMapping(value = "/payment/get/{id}")
    public RestResponse<Payment> getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentService.getPaymentById(id);
        if (payment != null) {
            return RestResponse.success(200, "查询成功,serverPort:  " + serverPort, payment);
        } else {
            return RestResponse.fail(444, "没有对应记录,查询ID: " + id, null);
        }
    }
    @PostMapping(value = "/payment/create")
    public RestResponse create(@RequestBody Payment payment) {
        int result = paymentService.create(payment);
        log.info("*****插入结果:" + result);
        if (result > 0) {
            return RestResponse.success(200, "插入数据库成功,serverPort: " + serverPort, result);
        } else {
            return RestResponse.fail(444, "插入数据库失败", null);
        }
    }

 }
  

6. 测试

先启动EurekaServer:7001和7002服务

再启动服务提供者 cloud-provider-payment8001查看服务注册情况
Eureka服务注册与发现_第10张图片cloud-provider-payment8001服务已经注册成功

测试服务是否正常: 访问 http://localhost/payment/get/1

Eureka服务注册与发现_第11张图片

Servce consumer 服务消费者

1.新建 cloud-consumer-order80微服务**

Eureka服务注册与发现_第12张图片

2、引入pom依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

3、application.yml配置

server:
  port: 80

spring:
    application:
        name: cloud-order-service

#eureka配置
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #defaultZone: http://localhost:7001/eureka # 单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
  instance:
    #向注册中心注册服务ID
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true #访问路径可以显示IP地址
    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30)
    lease-renewal-interval-in-seconds: 30
    #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90),超时将剔除服务
    lease-expiration-duration-in-seconds: 90

4、创建负载均衡配置类

Ribbon搭配Eureka实现负载均衡,在RestTemplate上添加@LoadBalanced注解

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;

/**
 * @auther
 * @desc Ribbon负载均衡配置类(Ribbon默认使用的是RoundRobinRule 轮询策略)
 */
@Configuration
public class LoadConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

5、主启动上添加@EnableEurekaClient

package com.my.springcloud;

import com.my.myrule.MyLoadConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient

public class OrderConsumer80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderConsumer80.class, args);
    }
}

6、编写controller


@RestController
@Slf4j
public class OrderController {
    public static final String INVOKE_URL = "http://cloud-provider-payment";
    @Resource
    private RestTemplate restTemplate;

     @GetMapping("/consumer/payment/get/{id}")
    public RestResponse<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, RestResponse.class);
    }
}

7、测试调用服务提供者

查看服务是否注册成功, 访问 http://localhost:7001/

Eureka服务注册与发现_第13张图片

8、验证下服务是否能被消费

生产环境部署都是多台实例,这里为了演示方便:模拟下多节点

在service中复制一个进程,指定不同端口
Eureka服务注册与发现_第14张图片

指定端口号
-Dserver.port=8002
Eureka服务注册与发现_第15张图片
启动刚才复制8003服务

查看服务是否注册成功, 访问 http://localhost:7001/

Eureka服务注册与发现_第16张图片8003服务已经注册到eureka中

测试调用服务提供者,是否能成功消费

(1)启动eureka 7001和7002,服务提供者8001和8002,服务消费者 consumer-order80
(2)访问 http://localhost/consumer/payment/get/1

Eureka服务注册与发现_第17张图片
在次发起请求

Eureka服务注册与发现_第18张图片端口号变成8003说明负载均衡成功

Eureka的自我保护机制

保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

简单一句话:(好死不如赖活着)

用电视剧新三国中,曹操说的:“宁可天下人负我,我不负天下人”即:Eureka服务端,进入自我保护模式,就算所有的微服务真的都出问题了,也不会里面删除它们的

为什么会出现自我保护机制?

一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该服务的信息进行保存。属于CAP里面的AP分支,也即是:保证可用性、分区容错性。
PS:CAP原则:分布式系统中,C:一致性;A:可用性;P:分区容错性。
我们来看看百度百科对CAP原则的详细介绍,如下图:

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

怎么禁止Eureka的自我保护?

1.在Eureka Service7001关闭自我保护机制

修改Eureka Service7001application.yml配置文件:
(1)关闭自我保护
(2)清除无效服务实例的时间间隔修改成2秒

eureka:
  server:
    #Eureka自我保护机制,(默认是开启的)
    enable-self-preservation: false
    # 清除无效服务实例的时间间隔修改成2秒
    eviction-interval-timer-in-ms: 2000

启动7001,访问 http://localhost:7001/

Eureka服务注册与发现_第20张图片
这句话的意思是: 关闭自我保护模式,在网络/其他问题的情况下,这可能无法保护实例过期。

2. Eureka client8001

修改Eureka client8001application.yml配置文件:
(1)修改eureka客户端向服务端发送心跳的时间间隔
(2)修改Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务

#eureka配置
eureka:
  instance:
    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30)
    lease-renewal-interval-in-seconds: 1
    #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90),超时将剔除服务
    lease-expiration-duration-in-seconds: 2

测试服务

启动7001和8001 ,访问 http://localhost:7001/

Eureka服务注册与发现_第21张图片
假如8001出现宕机

我这里直接模拟8001服务宕机:关闭8001服务

Eureka服务注册与发现_第22张图片

此时访问 http://localhost:7001/ 发现8001服务被剔除了

Eureka服务注册与发现_第23张图片

你可能感兴趣的:(springcloud,eureka,云原生)