码迷,mamicode.com
首页 > 编程语言 > 详细

spring-cloud-eureka服务注册与发现

时间:2019-04-19 15:57:54      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:inf   运行   service   直接   aws   联系   rgs   gap   plugin   

  Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
  Eureka包含两个组件:Eureka Server和Eureka Client。
  Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
  Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就别一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
  Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
  下面是Eureka基本的架构图
技术图片  

 上图简要描述了Eureka的基本架构,由3个角色组成:

  • Eureka Server:提供服务注册和发现
  • Service Provider:服务提供方,将自身服务注册到Eureka,从而使服务消费方能够找到
  • Service Consumer:服务消费方,从Eureka获取注册服务列表,从而能够消费服务。

 通过spring boot 搭建 Eureka-Server 

1.pom文件引入依赖,在SpringBoot(2.0.1)项目的基础上添加以下依赖

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR3</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- SpringCloud 所有子项目 版本集中管理. 统一所有SpringCloud依赖项目的版本依赖-->
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

    <build>
        <plugins>
            <plugin><!-- SpringBoot 项目打jar包的Maven插件 -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2. 配置文件application.yml

server:
  port: 7001

# eureka注册中心,不会盲目清楚已经注册的服务列表内的任何微服务,这是他的自我保护机制,
# 当微服务长时间没有客户端请求,即没有心跳,便会启动自我保护,
eureka:
  instance: #Eureka实例名,集群中根据这里相互识别
    hostname: eureka7001.com
  client:
    registerWithEureka: false #表示是否注册Eureka服务器,因为自身作为服务注册中心,所以为false
    fetchRegistry: false #是否从eureka上获取注册信息,因为自身作为服务注册中心,所以为false
    serviceUrl: #http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #集群版
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/

 3. 主启动类注解

@EnableEurekaServer // Eureka服务端注解
@SpringBootApplication
public class EurekaServerApp {public static void main(String[] args) {
        SpringApplication.run(EurekaServerApp.class,args);
        log.info("服务启动成功");

    }
}

   如上便完成了Eureka-Server的基本配置,接下去创建Service Provider 

1.pom文件引入依赖与上面保持一致即可。 

2. 配置文件application.yml

server:
  port: 8001

spring:
  application:
    name: cloud-provider #服务注册到Eureka上使用的名称

eureka:
  client:
    service-url:  # 集群情况下如下,如果是单机版,只需要配置单机版Eureka地址
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/
  instance:
    instance-id: cloud-provider-8001
    prefer-ip-address: true #访问路径显示IP地址

info:   # 在Eureka上点击服务时会跳转到个404页面,可配置这里让他跳转到服务简介的一个页面,信息如下配置
  app.name: wuzz
  company.name: www.wuzz.com
  build.artifactId: server-provider
  build.version: 1.0

3. 主启动类注解 

@EnableEurekaClient
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaServerProviderApp {
    private final static Logger log = LoggerFactory.getLogger(EurekaServerProviderApp.class);

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerProviderApp.class,args);
        log.info("服务启动成功");

    }
}

  如上便完成了Eureka-Server的基本配置,这样Eureka的服务的基本架构也基本完成。这里可以添加一个服务发现的Controller。

@RestController
public class TestController {

    @Autowired//服务发现
    private DiscoveryClient client;

    @GetMapping("/hello")
    public String helloEureka(){
         return  "Hello Eureka Provider";
    }

    /**
     * 服务发现
     * @return
     */
    @RequestMapping(value ="/discovery",method= RequestMethod.GET)
    public Object discovery() {
        List<String> list = client.getServices();
        List<ServiceInstance> instances = client.getInstances("");
        for(ServiceInstance instance  : instances) {
            System.out.println(instance.getHost());
        }
        return this.client;
    }
}

   下面来说说Eureka的一些基本问题:

为什么要有自我保护机制:

        众所周知,Eureka在CAP理论当中是属于AP , 也就说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性, 举个例子。当发生网络分区的时候,Eureka-Server和client端的通信被终止,server端收不到大部分的client的续约,这个时候,如果直接将没有收到心跳的client端自动剔除,那么会将可用的client端剔除,这不符合AP理论,所以Eureka宁可保留也许已经宕机了的client端 , 也不愿意将可以用的client端一起剔除。 从这一点上,也就保证了Eureka程序的健壮性,符合AP理论。 

  自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。 

  默认情况下,当eureka server在一定时间内没有收到实例的心跳,便会把该实例从注册表中删除(默认是90秒),但是,如果短时间内丢失大量的实例心跳,便会触发eureka   server的自我保护机制,比如在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:

EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY‘RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.

  从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。

  该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。

  但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:

  eureka.server.enable-self-preservation=false

  但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦终端,就无法恢复。

  当然关于自我保护还有很多个性化配置,这里不详细说明

  因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪

作为服务注册中心,Eureka比Zookeeper好在哪里:

著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。

Zookeeper保证CP

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。

Eureka保证AP

Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况: 
1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 
2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用) 
3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

Eureka Server集群宕机后,客户端是否可用?

情景一

Eureka Client 启动的时候,会主动去全量获取一次注册信息,如果这个时候Eureka Server集群

已经宕机,那么Eureka Client端是不可用的。

情景二

如果Eureka Client 启动时全量获取注册信息成功,在之后的运行过程当中,Eureka Server集群宕机了

那么这个时候,Eureka Client是不受影响的

 

spring-cloud-eureka服务注册与发现

标签:inf   运行   service   直接   aws   联系   rgs   gap   plugin   

原文地址:https://www.cnblogs.com/wuzhenzhao/p/9466752.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!