Eureka(服务注册和发现)——Eureka的简介和原理 & Eureka的使用和分析 & 心跳续约策略,服务的下线和剔除,自我保护 & Eureka集群的搭建

在这里插入图片描述

前言

Eureka:服务注册与发现组件,用于实现服务的自动注册与发现,Spring Cloud Eureka 是对Netflix公司的Eureka的二次封装,它实现了服务治理的功能,Spring Cloud Eureka提供服务端与客户端,服务端即是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。服务端和客户端均采用Java语言编写。

Eureka作为初代的服务注册和发现组件,其基本思想和原理对于后来的Nacos有深远的影响,在nacos中也能隐约看到其身影。

本篇博客介绍Eureka的简介和原理,结合实际使用阐述Eureka的使用并进行分析,此外,介绍了心跳续约策略,服务的下线和剔除以及自我保护,还有Eureka集群的搭建方式。

git代码仓库:https://gitee.com/pet365/spring-cloud-eureka

在这里插入图片描述

引出


1.Eureka的简介和原理;
2.结合实际使用阐述Eureka的使用并进行分析;
3.介绍了心跳续约策略,服务的下线和剔除以及自我保护;
4.Eureka集群的搭建方式,高可用;

Eureka初识

在这里插入图片描述

Eureka架构中的三个核心角色:

  • 服务注册中心
    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server。

  • 服务提供者
    提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的spring-provider。

  • 服务消费者
    消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中
    就是我们实现的spring-consumer。

有趣故事

Eureka的故事来源于人人追求真善美的古希腊,“Eureka”是希腊语,意思是“我发现了!”

这个有魔力的单词是来源于阿基米德。在公元前200多年,他在洗澡时发现了证明王冠是否纯金的方法(黄金密度),他激动地一边大喊“Eureka!”一边跳出澡盆奔去王宫,连衣服都忘了穿。后来人们用Eureka这个词来形容洞察浮现的瞬间。

SMS、库存、积分服务器,服务迁移变更等需要修改相应的URL地址,怎么不修改URL地址?

在微服务中,spring-provider对外提供服务,需要对外暴露自己的地址。而consumer(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦

这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦(没有人告诉哪些车私家车可以拉人),而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。

此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。

此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前,为你服务,完美!

Eureka做什么?

Eureka就好比是滴滴中心,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。

同时,服务提供方与Eureka之间通过“心跳” 机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。

这就实现了服务的自动注册、发现、状态监控。

Eureka是啥?

Eureka简介

在这里插入图片描述

Spring Cloud Eureka 是对Netflix公司的Eureka的二次封装,它实现了服务治理的功能,Spring Cloud Eureka提供服务端与客户端,服务端即是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。服务端和客户端均采用Java语言编写。

在这里插入图片描述

一个消费者和一个生产者

在这里插入图片描述

多个消费者与多个生产者

在这里插入图片描述

下图显示了Eureka Server与Eureka Client的关系

在这里插入图片描述

  • Eureka Server是服务端,负责管理各个微服务结点的信息和状态。
  • 在微服务上部署Eureka Client程序,远程访问Eureka Server将自己注册在Eureka Server。
  • 微服务需要调用另一个微服务时从Eureka Server中获取服务调用地址,进行远程调用。

原理

  • 服务提供方启动后将注册到注册中心,提供IP, 名字,什么服务等信息,
  • 服务调用方作为客户端注册到注册中心后,拉取注册中心的服务列表,在通过负载均衡调用对应的服务提供方。
  • 注册中心可以建立集群,生成多台eureka,注册中心为了监测各个服务的心跳,将在每30S 向所注册的服务发起请求判断
  • 服务是否挂掉,如果挂掉90S后将会将服务从注册中心剔除。
  • 一个服务可以监测多台服务实例,从而可实现均衡负载。

Eureka使用Hello案例

注册中心Eureka

引入依赖

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

eureka的配置文件

在这里插入图片描述

server:
  port: 9001 #  eureka默认端口号为8761
eureka:
  client:
    # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址
    service-url:
      defaultZone: http://127.0.0.1:${server.port}/eureka
    # 不把自己注册到eureka服务列表
    register-with-eureka: false
    # 拉取eureka服务信息
    fetch-registry: false #false表示自己就是注册中心,不需要从注册中心获取注册列表信息
  instance:
    #客户端在注册时使用自己的IP而不是主机名
    prefer-ip-address: true
    # 实例id
    instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}

logging:
  level:
    root: debug
配置说明:

register-with-eureka: false false表示不向注册中心注册自己

fetch-registry: false false表示自己就是注册中心,不需要从注册中心获取注册列表信息

service-url 设置eureka server交互的地址查询服务和注册服务都需要用到这个地址(单机用)

在这里插入图片描述

主启动类

在eureka-server的主启动类上开启eureka服务**@EnableEurekaServer**

在这里插入图片描述

package com.tianju.eureka;

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

@SpringBootApplication
@EnableEurekaServer // 声明当前springboot应用是一个eureka服务中心
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class);
    }
}

浏览器访问

启动eureka-server子项目,在浏览器上访问localhost:9001

在这里插入图片描述

查看日志

在这里插入图片描述

搭建生产者Provider

引入依赖

在这里插入图片描述

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

<!--        在provider的pom文件中添加监控依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

配置yml文件

在这里插入图片描述

server:
  port: 10010

eureka:
  client: #客户端注册到eureka列表中
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka
  instance:
    prefer-ip-address: true #显示访问url 客户端在注册时使用自己的IP而不是主机名
#    # 实例id
#    instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}
    instance-id: provider-10010  #注册中心显示出来的微服务名称

# 应用名称
spring:
  application:
    name: springCloud-provider

info:
  app.name: SpringCloud
  company.name: tianju
  build.artifactId: $project.artifactId$
  build.version: $project.version$

在这里插入图片描述

主启动类

在这里插入图片描述

package com.tianju.provider;

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

@SpringBootApplication
@EnableEurekaClient // 或 @EnableDiscoveryClient
public class ProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApp.class);
    }
}

在这里插入图片描述

@EnableEurekaClient和@EnableDiscoveryClient区别

在使用Spring Cloud feign使用中在使用服务发现的时候提到了两种注解:
一种为@EnableDiscoveryClient;
一种为@EnableEurekaClient,用法上基本一致

在这里插入图片描述

spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),

@EnableDiscoveryClient基于spring-cloud-commons;
@EnableEurekaClient基于spring-cloud-netflix。

其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient, 如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

注解@EnableEurekaClient上有@EnableDiscoveryClient注解,可以说基本就是EnableEurekaClient有@EnableDiscoveryClient的功能,另外上面的注释中提到,其实@EnableEurekaClient注解就是一种方便使用eureka的注解而已,可以说使用其他的注册中心后,都可以使用@EnableDiscoveryClient注解,但是使用@EnableEurekaClient的情景,就是在服务采用eureka作为注册中心的时候,使用场景较为单一。

查看日志

在这里插入图片描述

修改配置信息,变成了20s

lease-renewal-interval-in-seconds: 20 #心跳时间

在这里插入图片描述

server:
  port: 10010

eureka:
  client: #客户端注册到eureka列表中
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka
  instance:
    prefer-ip-address: true #显示访问url 客户端在注册时使用自己的IP而不是主机名
#    # 实例id
#    instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}
    instance-id: provider-10010  #注册中心显示出来的微服务名称
    lease-renewal-interval-in-seconds: 20   #心跳时间
    lease-expiration-duration-in-seconds: 60 #下线时间

# 应用名称
spring:
  application:
    name: springCloud-provider

info:
  app.name: SpringCloud
  company.name: tianju
  build.artifactId: $project.artifactId$
  build.version: $project.version$

搭建消费者consumer

引入依赖配置等雷同

在这里插入图片描述

注册到eureka

在这里插入图片描述

主启动类

在这里插入图片描述

package com.tianju.consumer;

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 org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class);
    }

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

在生产端提供controller

在这里插入图片描述

在消费端调用生产者

在这里插入图片描述

package com.tianju.consumer.controller;

import com.netflix.appinfo.InstanceInfo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/consumer")
@Slf4j
public class ConsumerController {

    @Resource
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/getId/{id}")
    public String getMsg(@PathVariable("id") String id) {
        List<ServiceInstance> instances = discoveryClient.getInstances("springCloud-provider");
        ServiceInstance instance = instances.get(0);
        String host = instance.getHost();
        int port = instance.getPort();
        log.debug("消费者拼出路径+端口:"+ host+":"+port);

        // 获取ip和端口信息,拼接成服务地址
        String baseUrl = "http://" + instance.getHost() + ":" +
                instance.getPort() + "/provider/get/" + id;
        String consumer = restTemplate.getForObject(baseUrl, String.class);

        log.debug("采用restTemplate调用生产者:"+baseUrl);
        return "消费者调用生产者获得消息:"+consumer;
    }
}

在这里插入图片描述

心跳和续约策略

Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址

  • 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
  • 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

在这里插入图片描述

常见概念

Register 服务注册

当Eureka客户端向Eureka Server注册时,它提供自身的元数据,比如IP地址、端口,运行状况指示符URL,主页等。

Renew 服务续约(心跳机制)

Eureka客户会每隔30秒发送一次心跳来续约。通过续约来告知Eureka Server该Eureka客户仍然存在,没有出现问题。正常情况下,如果Eureka Server在90秒没有收到Eureka客户的续约,它会将实例从其注册表中删除。建议不要更改续约间隔。

  • 心跳机制是每隔30秒发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制。
  • 心跳机制是每隔30秒发送一个固定信息给服务端,服务端收到后回复一个固定的信息。如果服务端90秒内没有收到客户端消息则视客户端断开。
  • 发送方可以是客户端或服务端,根据实际情况,一般是客户端;因为一个服务端可能有很多客户端,服务端作为发送方的比较耗费性能。

Fetch Registries 获取注册列表信息

Eureka客户端从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与Eureka客户端的缓存信息不同, Eureka客户端自动处理。如果由于某种原因导致注册列表信息不能及时匹配,Eureka客户端则会重新获取整个注册表信息。 Eureka服务器缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka客户端和Eureka 服务器可以使用JSON / XML格式进行通讯。在默认的情况下Eureka客户端使用压缩JSON格式来获取注册列表的信息。

服务的下线和剔除

Cancel 服务下线

Eureka客户端在程序关闭时向Eureka服务器发送取消请求,发送请求后,该客户端实例信息将从服务器的实例注册表中删除,该下线请求不会自动完成,它需要调用以下内容:

DiscoveryManager.getInstance().shutdownComponent();

服务进行正常关闭操作,会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。

Eviction 服务剔除

在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约(心跳),Eureka服务器会将该服务实例从服务注册列表删除,即服务剔除。

有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。

可以通过eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒。

eureka:
	server:
		# 每隔多久(ms)触发一次服务剔除
		eviction-interval-timer-in-ms: 10000

在这里插入图片描述

自我保护

我们关停一个服务,就会在Eureka面板看到一条警告:

在这里插入图片描述

这是触发了Eureka的自我保护机制。当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服务实例的比例是否超过了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。

Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。

但是这给我们的开发带来了麻烦, 因此开发阶段我们都会关闭自我保护模式:(eureka-server)

eureka:
	server:
		enable-self-preservation: false # 如果为true,表示要保护实例,不被剔除,false关闭自我保护模式,剔除实例
		eviction-interval-timer-in-ms: 10000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

如果保护实例不被剔除,而且配置了 eviction-interval-timer-in-ms: 10000,则eviction-intervaltimer-in-ms参数为准,实例还是会被剔除

eureka:
	server:
		enable-self-preservation: true # 如果为true,表示要保护实例,不被剔除,false关闭自我保护模式,剔除实例
		#eviction-interval-timer-in-ms: 10000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

Eureka集群搭建

Eureka Server即服务的注册中心,在刚才的案例中,我们只有一个EurekaServer,事实上EurekaServer也可以是一个集群,形成高可用的Eureka中心。

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。

因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

允许多个实例

在这里插入图片描述

1.启动第一个

所谓的高可用注册中心,其实就是把EurekaServer自己也作为一个服务进行注册,这样多个EurekaServer之间就能互相发现对方,从而形成集群。因此我们做了以下修改:把service-url的值改成了另外一台EurekaServer的地址,而不是自己。

先启动一个

在这里插入图片描述

在这里插入图片描述

启动报错,很正常。因为另一个服务没有启动

在这里插入图片描述

2.再启动一个

启动第二个eurekaServer,再次修改eureka-server的配置

再启动一个

在这里插入图片描述

3.访问集群

集群效果

在这里插入图片描述

4.客户端注册

因为EurekaServer不止一个,因此注册服务的时候,service-url参数需要变化:

在这里插入图片描述

5.注册效果

在这里插入图片描述

在这里插入图片描述


总结

1.Eureka的简介和原理;
2.结合实际使用阐述Eureka的使用并进行分析;
3.介绍了心跳续约策略,服务的下线和剔除以及自我保护;
4.Eureka集群的搭建方式,高可用;

  • 11
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Eureka 是 Netflix 开源的一个基于 RESTful 的服务注册发现组件,用于服务注册发现Eureka 分为 Eureka Server 和 Eureka Client 两部分。Eureka Server 作为服务注册中心,负责服务注册发现Eureka Client 则作为服务提供者和服务消费者的客户端,通过向 Eureka Server 注册发现服务Eureka Client 启动后会向 Eureka Server 发送心跳包,以保持与 Eureka Server 的连接,同时将自己注册Eureka Server 上。Eureka Server 则会维护一个服务注册表,记录所有已注册服务列表。当服务提供者启动时,它会向 Eureka Server 发送一个注册请求,告诉 Eureka Server 它的服务实例已经启动。当服务消费者需要调用某个服务时,它会向 Eureka Server 发送一个发现请求,Eureka Server 则会返回该服务的所有实例列表,消费者可以根据负载均衡策略选择其中的一个实例进行调用。 在 Eureka Client 向 Eureka Server 发送心跳包时,Eureka Server 会将该服务实例的状态设置为 UP。如果 Eureka Server 在一定时间内没有收到该服务实例的心跳包,就会将该服务实例的状态设置为 DOWN,并从服务注册表中删除该实例。当服务提供者关闭时,它会向 Eureka Server 发送一个取消注册请求,告诉 Eureka Server 它的服务实例已经关闭,Eureka Server 则会将该服务实例从服务注册表中删除。 总之,Eureka 注册中心和客户端的请求原理是基于 RESTful 风格的。Eureka Client 通过向 Eureka Server 发送注册发现请求,实现服务注册发现Eureka Server 则维护服务注册表,记录所有已注册服务列表,并根据心跳包更新服务实例的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Perley620

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值