SpringCloud服务注册中心——Eureka

Eureka

本专栏学习内容来自尚硅谷周阳老师的视频

有兴趣的小伙伴可以点击视频地址观看

简介

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。

SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

Eureka现已停更,但停更不停用

基础知识

Eureka包含两个组件:Eureka ServerEureka Client

Eureka Server提供服务注册服务

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

EurekaClient通过注册中心进行访问

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

单机Eureka

单机Eureka是通过将服务注册到一个Eureka服务中心去,如下图所示

在这里插入图片描述

Eureka服务注册中心

此服务只是一个注册服务,只需要一个启动类+配置文件即可

首先得引入Eureka服务端的依赖

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

接着修改配置文件,因为本身就是注册中心,所以不需要向注册中心去注册自己

server.port=7001

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

最后只需要在启动类上加如下注解

@EnableEurekaServer

启动服务,可以看到Eureka的交互式页面,此处表示还没有服务注册进来

在这里插入图片描述

消费者

在微服务中,经常会有一个服务调用另外一个服务的情况,在这里我们将前者称之为消费者,后者称之为提供者。现在我们需要把消费者也注册到服务中心

首先引入Eureka客户端依赖

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

修改配置文件

server.port=80
spring.application.name=cloud-order-service

#eureka
#true表示向注册中心注册自己。
eureka.client.register-with-eureka=true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
eureka.client.fetch-registry=true
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
eureka.client.service-url.defaultZone=http://localhost:7001/eureka

在启动类上加上如下注解

@EnableEurekaClient

到这一步我们就已经修改完毕,这时候启动消费者,发现此服务已经被注册到服务中心

需要注意的是注册名与spring.application.name相关,一旦定下来,轻易不要修改

在这里插入图片描述

提供者

提供者修改与消费者完全相同,这里就不再赘述,现在我们的工程目录就变成了这个样子

commons是我们的公共包

7001是Eureka服务注册中心

80是消费者

8001是提供者

在这里插入图片描述

集群Eureka

在开发中,我们常常会使用到集群,为了防止Eureka服务注册中心挂掉,会对Eureka进行集群处理。

Eureka集群

以下是我们需要实现的图示,实现集群的关键点在于,两个服务相互注册

在这里插入图片描述

我们根据cloud-eureka-server7001复制一个cloud-eureka-server7002

因为是测试环境在本地,所有的ip都是localhost,为了区分两个服务,可以修改映射配置添加进hosts文件

127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com

接下来我们需要分别修改7001配置文件和7002配置文件,将7001注册进7002的服务中心,反之亦然

#eureka服务端的实例名称
eureka.instance.hostname=eureka7001.com  #修改
#false表示不向注册中心注册自己。
eureka.client.register-with-eureka=false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
eureka.client.fetch-registry=false
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
eureka.client.service-url.defaultZone=http://eureka7002.com:7002/eureka/   #修改

分别启动两个注册中心服务,会发现他们已经相互注册成功

在这里插入图片描述

此时,集群已经配置完毕,我们还需要将消费者和提供者分别注册到集群的服务中心

修改两个服务的配置文件即可

eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  

至此,我们就完成了Eureka集群的搭建

在这里插入图片描述

多个提供者

在实际开发过程中,为了降低服务压力,还需要实现多个提供者的集群,如下图所示

在这里插入图片描述

现在我们需要根据cloud-provider-payment8001复制一个cloud-provider-payment8002服务,此时Eureka页面中加载了两个CLOUD-PAYMENT-SERVICE

在这里插入图片描述

调用消费者接口,发现无论如何调用的都是8001的服务,那是因为消费者接口是如下的

@RestController
@Slf4j
public class OrderController {
    
    

    public static final String PaymentSrv_URL = "http://localhost:8001";

    @Resource
    RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult createPayment(Payment payment){
    
    
        return restTemplate.postForObject(PaymentSrv_URL + "/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult createPayment(@PathVariable Integer id){
    
    
        return restTemplate.getForObject(PaymentSrv_URL + "/payment/get/" + id,CommonResult.class);
    }
}

在配置URL时,写死了访问地址,现在需要把地址改成服务注册中心中application的服务名

public static final String PaymentSrv_URL = "http://CLOUD-PAYMENT-SERVICE";

这时候我们调用服务还会报错,这是因为服务注册中心有两个CLOUD-PAYMENT-SERVICE,消费者不知道需要去调用哪个

在这里插入图片描述

这时候要使用@LoadBalanced注解赋予RestTemplate负载均衡的能力,此时在测试可以发现8001、8002服务交替被调用

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

actuator微服务信息完善

服务名称修改

如下图所示,我们注册的服务含有主机名称

在这里插入图片描述

这个名称可以通过配置文件自定义

#服务主机名称
eureka.instance.instance-id=payment8002

在这里插入图片描述

访问信息有ip提示信息

只需要添加如下配置

#访问信息有ip提示
eureka.instance.prefer-ip-address=true

在这里插入图片描述

服务发现Discovery

对于注册进Eureka里的微服务,可以通过服务发现来获得该服务的信息

需要在主启动类上加入@EnableDiscoveryClient,这个注解我们将会经常使用,使用方法如下

    @Resource
    private DiscoveryClient discoveryClient;    

		@GetMapping(value = "/discovery")
    public Object discovery()
    {
    
    
      	// 获取服务名称
        List<String> services = discoveryClient.getServices();
        for (String element : services) {
    
    
            System.out.println(element);
        }

        // 获取服务的实例
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance element : instances) {
    
    
            System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
                    + element.getUri());
        }
        return this.discoveryClient;
    }

Eureka自我保护

为什么会产生Eureka自我保护机制?

为了防止EurekaClient可以正常运行,但是 与 EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除

什么是自我保护模式?

默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。

它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着

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

默认情况下,Eureka是开启自我保护,可以使用eureka.server.enable-self-preservation = false 可以禁用自我保护模式

猜你喜欢

转载自blog.csdn.net/Yellow_Star___/article/details/129506048