SpringCloud_Eureka注册中心

在之前的案例中,服务消费方是通过RestTemplate直接调用服务提供方,显然是不合适的。接下来通过优化案例引入SpringCloud的组件Eureka注册中心来完成服务的注册与发现以及管理。

注册中心原理图:
在这里插入图片描述

一、添加Eureka注册中心的Module

1、新建一个Maven工程

2、补充pom.xml文件,引入Eureka启动器

 <!--定义SpringCloud的版本号-->
    <properties>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>

    <!--引入Eureka启动器-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <!--统一管理SpringCloud版本号-->
    <dependencyManagement>
        <dependencies>
            <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、覆盖默认配置

server:
  port: 10086
spring:
  application:
    name: xsh-eureka  #微服务的名称,将来会作为服务名注入到eureka容器中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka  #表示eureka服务器端的地址

其中spring.application.name表示微服务的名称,每一个微服务都需要配置这个名称,用于作为注入到注册中心的服务名称。

补充:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect错误的解决方式

在application.yml文件中补充如下配置:

eureka.client.fetch-registry: flase
#该配置表示注册中心不检索服务

4、在引导类上添加注解启用eureka服务端

package com.xsh.eureka;

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

@SpringBootApplication
@EnableEurekaServer    //启用Eureka服务端
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

至此,eureka注册中心就搭建完成,按照如上配置,通过http://localhost:10086即可访问。

二、将服务提供方和服务消费方注入到eureka注册中心

1、修改pom.xml文件,引入eureka客户端依赖

 <!--定义SpringCloud的版本号-->
    <properties>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>
     <dependencies>
   	    <!--引入eureka客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    <!--统一管理SpringCloud版本号-->
    <dependencyManagement>
        <dependencies>
            <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>

2、修改application.yml配置

sping:
  application:
    name: service-producer  #微服务名称
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka   #注册中心地址

3、在引导类上添加注解启用eureka客户端

package com.xsh.producer;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@MapperScan(basePackages = {"com.xsh.producer.mapper"})
@EnableDiscoveryClient  //启用eureka客户端
public class ProducerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class,args);
    }
}

服务消费方也是一样,通过如上步骤,就可以将服务提供方和服务消费方注册到eureka注册中心。
在这里插入图片描述

三、改造之前案例的硬编码问题

在之前的入门案例中,我们的服务提供方和服务消费方是通过RestTemplate进行直接调用的,为了改善这种情况我们加入了eureka注册中心来管理服务。

但是服务调用还存在硬编码的问题:

@RequestMapping("/{uid}")
    public User findByid(@PathVariable Integer uid){
        return restTemplate.getForObject("http://localhost:8081/user/findByid/"+uid,User.class);
    }

在以上的调用方法中,目标接口的地址路径是写死的,此时如果服务提供方是一个集群的方式的话,这种调用显然是不合理的,接下来通过eureka来进行动态的获取调用路径改良代码:

package com.xsh.consumer.controller;

import com.xsh.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
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 java.util.List;

@RestController
@RequestMapping("/consumer/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;  //该对象包含了从注册中心拉取的服务列表信息


    @RequestMapping("/{uid}")
    public User findByid(@PathVariable Integer uid){
        List<ServiceInstance> instances = discoveryClient.getInstances("SERVICE-PRODUCER");
        ServiceInstance serviceInstance = instances.get(0);
        return restTemplate.getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/user/findByid/"+uid,User.class);
    }
}

通过DiscoveryClient对象来获取服务列表信息来改善硬编码问题。

四、eureka详解

1、基础架构

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

  • 服务注册中心:eureka的服务端应用,提供服务注册和发现功能。
  • 服务提供者:提供服务的应用,可以是SpringBoot应用,也可以是其他任意技术实现,只要对外提供Rest风格的服务接口即可,
  • 服务消费者:消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。

2、高可用的eureka配置

微服务的集群配置就是除了增加并发量之外还可以避免当某台服务器宕机之后服务就无法使用的现象,同样的erureka注册中心也会有宕机的风险,此时我们就要配置高可用的注册中心集群。

配置注册中心的集群自然要将eureka在多个服务器上进行配置,然后我们只需要让每个eureka之间相互注册就可以完成高可用配置:

①例如:10086、10087两台服务器进行相互注册配置

server:
  port: 10087
spring:
  application:
    name: xsh-eureka  #微服务的名称,将来会作为服务名注入到eureka容器中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka  #表示eureka服务器端的地址
    fetch-registry: false    #注册中心的职责是维护服务实例,false:不检索服务
server:
  port: 10086
spring:
  application:
    name: xsh-eureka  #微服务的名称,将来会作为服务名注入到eureka容器中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10087/eureka  #表示eureka服务器端的地址
    fetch-registry: false    #注册中心的职责是维护服务实例,false:不检索服务

②访问两个eureka发现服务列表数据都是共享的
在这里插入图片描述
此时,就完成了eureka的高可用配置,当某个eureka宕机之后,另外的eureka服务器也会继续进入使用。
在此,相互注册的注册中心没有先后顺序之分,例如10086的注册中心先启动,找不到10087的注册中心就会报错,但是10086会持续请求,当10087启动之后请求成功就可以完成相互注册。

3、服务提供者

服务提供者要向EurekaServer注册服务,并且完成服务续约等工作。

①服务注册
服务提供者在启动时,会检测配置属性中的:eureka.client.register-with-eureka=true参数是否正确,事实上默认取值就是true。如果值为true,则会向EureServer发起一个Rest请求,并携带自己的元数据信息,EurekaServer则会把这些信息保存到一个双层Map结构中:

  • 第一层Map的key就是服务id,一般是配置中spring.application.name属性
  • 第二层Map的key是服务的实例id,一般是"host+serviceid+post",例如:“localhost:user-service:8081”。值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同示例,形成集群。

②服务续约
在服务注册完成之后,服务提供者会维持一个心跳(定时向EurekaServer发送Rest请求),告诉EurekaServer“我还活着”,这个我们称之为服务的续约(renew);

有两个重要的参数可以修改服务续约的行为:

eureka:
  instance:
    lease-expiration-duration-in-seconds: 90
    lease-renewal-interval-in-seconds: 30

lease-expiration-duration-in-seconds:服务失效时间,默认为90秒
lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒

也就是说,默认情况下每隔30秒就会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳,EurekaServer就会默认该服务宕机,会从服务列表中移除。
这两个值在生产环境下不用进行更改,在开发环境下,如果觉得时间太长,影响效果和测试,可以适当的改小一些:

eureka:
  instance:
    lease-expiration-duration-in-seconds: 15  #15秒过期
    lease-renewal-interval-in-seconds: 5   #5秒发送一次心跳

4、服务消费者

当服务消费者启动时,会检测eureka.client.fetch-registry=true参数的值,如果为true,则会拉取EurekaServer服务的列表进行只读备份,然后缓存在本地,并且每隔30秒会重新获取并更新数据。
我们可以通过以下的参数来修改获取数据的时间:

eureka:
  client:
    registry-fetch-interval-seconds: 5

同样,在生产环境中我们不需要修改这个值。
在开发环境下,如果想要快速获得服务的最新状态,就可以把这个值设置得小一些。

5、失效剔除和自我保护

①服务下线
当服务进行正常关闭操作时,它会触发一个服务下线的Rest请求发送给EurekaServer,告诉服务注册中心:"我要下线了“。服务注册中心接收到请求之后,将该服务置为下线状态。

②失效剔除
有的时候,我们的服务提供方不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。EurekaServer需要将这样的服务剔除出服务列表,因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应) 进行剔除。
我们可以通过eureka.server.eviction-interval-timer-in-ms参数对其进行设置,因为在开发环境下默认时间对于我们来说有点太长了,对服务进行了重启,隔了60秒Eureka才反应过来。

eureka:
    server:
    eviction-interval-timer-in-ms: 5000  #设置剔除响应时间为5

③自我保护机制
当我们关闭一个服务之后,其实Eureka并不会立即将该服务从服务列表中剔除,此时会触发Eureka的自我保护机制。
当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服务实例的比例是否超过了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就将服务剔除出列表并不妥当,因为服务可能没有宕机。
所以Eureka会在这种情况下把当前实例的注册信息保护起来,不予剔除。
生产环境下这很有效,保证了大多数服务依然可用,但是这给开发环境带来了麻烦,所以开发阶段我们一般会关闭Eureka的自我保护机制。

eureka:
  server:
    enable-self-preservation: false  #关闭自我保护模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值