Spring Cloud服务注册-Eureka介绍和部署

1、Spring-Cloud Euraka介绍

Spring-Cloud Euraka是Spring Cloud集合中一个组件,它是对Euraka的集成,用于服务注册和发现。Eureka是Netflix中的一个开源框架。它和 zookeeper、Consul一样,都是用于服务注册管理的,同样,Spring-Cloud 还集成了Zookeeper和Consul。

在项目中使用Spring Cloud Euraka的原因是 它可以利用Spring Cloud Netfilix中其他的组件,如zull等,因为Euraka是属于Netfilix的。

2、Euraka介绍

Eureka由多个instance(服务实例)组成,这些服务实例可以分为两种:Eureka Server和Eureka Client。为了便于理解,我们将Eureka client再分为Service Provider和Service Consumer。

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

1.1 Eureka与Zookeeper比较

首先介绍下cap原理,可以参考:http://www.ruanyifeng.com/blog/2018/07/cap.html

  • P:Partition tolerance,网络分区容错。类似多机房部署,保证服务稳定性。
  • A: Availability,可用性。
  • C:Consistency ,一致性。

CAP定理:CAP三个属性对于分布式系统不同同时做到。如AP/CP/AC。再来看Zookeepr区别:

(1)Zookeeper是CP,分布式协同服务,突出一致性。对ZooKeeper的的每次请求都能得到一致的数据结果,但是无法保证每次访问服务可用性。如请求到来时,zookeer正在做leader选举,此时不能提供服务,即不满足A可用性。

(2)Euere是AP,高可用与可伸缩的Service发现服务,突出可用性。相对于Zookeeper而言,可能返回数据没有一致性,但是保证能够返回数据,服务是可用的。

这里有篇文章介绍为什么服务发现使用Eureka,而不是Zookeeper。https://medium.com/knerd/eureka-why-you-shouldnt-use-zookeeper-for-service-discovery-4932c5c7e764

中文翻译 http://dockone.io/article/78

2 部署Eureka Server

分为手动和自动两种方式。

2.1 手动

1、pom.xml

<groupId>com.examplegroupId>
    <artifactId>eureka-demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>Eureka-DeMOname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.9.RELEASEversion>
        <relativePath/>
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Edgware.RELEASEspring-cloud.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eureka-serverartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

注意以下几点:

2、启动类

通过@EnableEurekaSwerver来标识该服务为Eureka Server。

1 @SpringBootApplication
2 @EnableEurekaServer
3 public class EurekaDeMoApplication {
4
5     public static void main(String[] args) {
6         SpringApplication.run(EurekaDeMoApplication.class, args);
7     }
8 }

3、配置文件有两种:.properties和 .yml 两种文件,可以任务选一种,这里使用properties文件。

对于.properties使用”.”来隔开;.yml 文件采用树状分级结构,对于yml文件规范,可以参考http://www.ruanyifeng.com/blog/2016/07/yaml.html

(1)applicaiton.properties文件格式如下:

server.port=8761
eureka.instance.hostname=localhost
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8761/eureka/

(2)applicaiton.yml格式如下:

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:8761/eureka/

3、工程目录如下

Spring Cloud服务注册-Eureka介绍和部署

2.2 自动生成

通过使用一个Idea自动新建一个工程

1、选择”Spring Initailizr”

Spring Cloud服务注册-Eureka介绍和部署

2、选择”Eureka Server”,

Spring Cloud服务注册-Eureka介绍和部署

3、自动生成之后,如下目录

Spring Cloud服务注册-Eureka介绍和部署

4、自动生成之后,可能还需要一些改动

(1)启动类需要添加@EnableEurekaServer。

1 @SpringBootApplication
2 @EnableEurekaServer
3 public class EurekaDeMoApplication {
4 ....

5 }

(2) 删除mvnw相关文

mvnw的介绍可以参考:http://www.javacoder.cn/?p=759。在一个项目中设计文件目录为

Spring Cloud服务注册-Eureka介绍和部署

因为暂时不使用mvnw,所以删除如下文件

  • .mvn目录
  • mvnw和mvnw.cmd两个文件

2.3 admin页面属性

1、启动,访问http://localhost:8761/

Spring Cloud服务注册-Eureka介绍和部署

3 部署Eureka Client

1、Eureka Client包括两个服务模块:Service Provider(服务提供方)和Service Consumer(服务消费方)。

2、Eureka Client和Eureka Server目录类似, 不同点在于:

  • 启动类,使用@EnableDiscoveryClient 标识该服务为Euraka Client
  • 配置文件,需要指定Euraka Server地址和当前服务注册时的名称。

3.1 部署 Servcie Provider

工程目录为

Spring Cloud服务注册-Eureka介绍和部署

1、pom.xml文件

<groupId>com.examplegroupId>
    <artifactId>demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>demoname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.9.RELEASEversion>
        <relativePath/>
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Edgware.RELEASEspring-cloud.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

2、启动类

使用@EnalbeDiscoveryClinet标识当前服务为Euraka Client。

1 @SpringBootApplication(scanBasePackages = {"com.example"})
2 @EnableDiscoveryClient
3 public class DemoApplication {
4
5     public static void main(String[] args) {
6         SpringApplication.run(DemoApplication.class, args);
7     }
8 }

3、请求函数

1 @Controller
 2 public class FirstController {
 3
 4     @RequestMapping("/query")
 5     @ResponseBody
 6     public ViewVo query() {
 7         ViewVo vo = new ViewVo();
 8         vo.setName("hoho");
 9         vo.setDecription("with dgold 123");
10         return vo;
11     }
12 }

4、配置文件

eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
server.port=8762
spring.application.name=service-prodvider1

参数说明:

  • eureka.client.serviceUrl.defaultZone:指定Eureka Server的地址
  • spring.application.name:置在Eureka Server进行注册时,当前服务的名称。

5、结果为

查看admin页面:http://localhost:8761/,如下存在了名字为”service-prodvider1″的服务。

Spring Cloud服务注册-Eureka介绍和部署

3.2 部署 Servcie Customer

如下是客户端从Euraka Server中获取到服务的地址信息:

1、工程目录和Servie Providerder一样的。

为了从Euraka Server中获取服务地址信息,在上面Serice Proder工程中添加一个Controler,如下

1 @Controller
 2 public class ClientControlelr {
 3     @Autowired
 4     private DiscoveryClient discoveryClient;
 5
 6     @RequestMapping("/queryService")
 7     @ResponseBody
 8     public ViewVo query() {
 9         List instances =discoveryClient.getInstances("service-prodvider1");
10         StringBuilder urls= new StringBuilder();
11         for(ServiceInstance instance : instances){
12             urls.append(instance.getHost()+":"+instance.getPort()).append(",");
13         }
14         ViewVo vo = new ViewVo();
15         vo.setName("service-prodvider1");
16         vo.setDecription(urls.toString());
17         return vo;
18     }
19 }

2、执行 http://localhost:8762/queryService ,结果为

{“name”:”service-prodvider1″,”decription”:”192.168.0.103:8762,”}

3、问题:关于Servie Customer是否需要在Euraka Server中进行注册呢?

不一定。Service Customer只是从Eureka Serve中获取注册服务的地址信息,如果Service Customer 本身也是一个Service Porvider,那么此时就需要注册服务了。

Spring Cloud服务注册-Eureka介绍和部署

4 常见问题

4.1 自我保护机制

1、问题描述

在admin页面出现如下错误”EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.”,如下图

Spring Cloud服务注册-Eureka介绍和部署

2、自我保护模式介绍

参考官网:https://github.com/Netflix/eureka/wiki/Understanding-Eureka-Peer-to-Peer-Communication

保护模式,是Eureka 提供的一个特性,在默认的情况下,这个属性是打开的,而且也建议线上都使用这个特性。

如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,此时会触发Eureka Server进入保护模式,进入自我保护模式后,将会保护服务注册表中的信息,不再删除服务注册表中的数据。

3、关于上面的问题

在上面测试过程中,只有一个Eureka Client,当这个Eureka Client服务注册后,又被关停了,就导致Eureka Client进入了保护模式。所以上面警告信息是Eureka Server进入自我保护模式之后的显示的。

4、相关属性设置

对于自我保护模式属性,建议都是使用默认的配置,不需要要设置这些属性。

(1)Eureka Server端

默认情况下自我保护机制是打开的,线上建议都是打开的,即不需要设置。如果在测试环境需要设置为关闭,可以通过如下配置:

设为false,关闭自我保护。默认是打开的。
eureka.server.enable-self-preservation=false

设置清零失效服务的间隔时间,但是不建议更改

清理间隔(单位毫秒,默认是60*1000)
eureka.server.eviction-interval-timer-in-ms=4000

这个”eureka.server.eviction-interval-timer-in-ms”时间,是Eureka Server执行清理无效服务的时间间隔,执行新清理任务时,如果下面判断生效,则清除服务。

当前时间 - 上次心跳时间 > lease-expiration-duration-in-seconds

其中,lease-expiration-duration-in-seconds 属性在客户端进行配置

这里一个规范就是: 服务端的”eureka.server.eviction-interval-timer-in-ms” 值 要比 客户端配置 “lease-expiration-duration-in-seconds “的时间短。

(2) Eureka Client端

开启健康检查,默认是开启的,如下

eureka.client.healthcheck.enabled=true

心跳相关的设置

单位是秒,默认30秒。此客户端发送心跳的频率
eureka.instance.lease-renewal-interval-in-seconds=30

单位是秒,默认90秒,表示eureka server在收到此client上次心跳之后,间隔多久没有收到,就摘除此服务。
eureka.instance.lease-expiration-duration-in-seconds=10

4.2 kill -9 注册中心自动下线实例

在客户度服务kill -9或者宕机之后,需要自动从主从中心下掉。

1、服务端配置

_因为我们测试实例只有一个,所以这里关闭了自我保护,在生成环境不需要设置这个属性,默认是打开的。_因为开启自我保护,客户端是单实例时候,在被kill -9 之后是不会从注册中心下掉的,开启自我保护要保护注册中心注册表信息。

单位是秒,默认30秒。此客户端发送心跳的频率
eureka.instance.lease-renewal-interval-in-seconds=10
单位是秒,默认90秒,表示eureka server在收到此client上次心跳之后,间隔多久没有收到,就摘除此服务。
eureka.instance.lease-expiration-duration-in-seconds=15
清理间隔(单位毫秒,默认是60*1000)
eureka.server.eviction-interval-timer-in-ms=3000
设为false,关闭自我保护。默认是打开的。
eureka.server.enable-self-preservation=false

2、客户端配置

单位是秒,默认30秒。此客户端发送心跳的频率
eureka.instance.lease-renewal-interval-in-seconds=10
单位是秒,默认90秒,表示eureka server在收到此client上次心跳之后,间隔多久没有收到,就摘除此服务。
eureka.instance.lease-expiration-duration-in-seconds=15

3、测试结果

发现需要28s左右自动下线。为什么是28s?

eureka.instance.lease-renewal-interval-in-seconds + eureka.instance.lease-expiration-duration-in-seconds =25秒。由于定时任务间隔为3s,所以下线时间预计为25s~25+3s 之间。所以下线时间间隔为:

“eureka.instance.lease-renewal-interval-in-seconds + eureka.instance.lease-expiration-duration-in-seconds” 到 “eureka.instance.lease-renewal-interval-in-seconds + eureka.instance.lease-expiration-duration-in-seconds + eureka.server.eviction-interval-timer-in-ms”

5 Eureka操作

5.1 查看服务实例信息

查看服务实例信息。格式如下

/eureka/apps/{appName}

举例如下:

方法 GET

接口 http://localhost:8761/eureka/apps/SERVICE-PRODVIDER1

结果为:

<application>
<name>SERVICE-PRODVIDER1name>   ## 服务名字
<instance>
<instanceId>192.168.0.106:service-prodvider1:8762instanceId>  ## 实例ID
<hostName>192.168.0.106hostName>
<app>SERVICE-PRODVIDER1app>
<ipAddr>192.168.0.106ipAddr>
<status>UPstatus>
<overriddenstatus>UNKNOWNoverriddenstatus>
<port enabled="true">8762port>
<securePort enabled="false">443securePort>
<countryId>1countryId>
....

5.2 下线操作

5.2.1 客户端直接停止服务

1、下线

这种方式没有办法立刻让注册中心感知到,需要注册中心等待某一时间没有收到心跳之后,才将这个服务从注册列表中移除。

2、恢复上线

此种方式下对应上线操作,就是重新部署。

5.2.2 客户端通知Eureka下线

1、 下线

使用actuator由客户端发起下线。调用客户端actuator提供的/shutdown/接口。执行完此操作之后,不仅停止了服务,还从eureka下线了。

(1)在项目中引用actuator:

1 <dependency>
2     <groupId>org.springframework.bootgroupId>
3     <artifactId>spring-boot-starter-actuatorartifactId>
4 dependency>

(2)配置文件中添加

#启用shutdown
endpoints.shutdown.enabled=true
#不进行密码验证(线上环境应该设置为true)
management.security.enabled=false

(3)通过 _POST方式_执行实例的http://localhost:8765/shutdown。在postman执行结果如下:

Spring Cloud服务注册-Eureka介绍和部署

2、恢复上线

重新部署服务

5.2.3 Eureka的delete操作

1、下线

delete格式为:

方法:DELETE

接口:/eureka/apps/{appName}/{instanceID}

参数中appName和instaceId可以由查看服务实例信息接口获取,也可以通过erueka admin获取,如下

Spring Cloud服务注册-Eureka介绍和部署

注意: Eureka客户端每隔一段时间(默认30秒)会发送一次心跳到注册中心。在通过delte方式下线一个服务时,如果没有停掉的该服务,那么该服务很快就又会注册到Eureka。所以在使用这种方式时,可以先kill掉服务,然后再执行delete操作,从注册中心移除改服务。

2、恢复上线

在此种方式下就是重新部署服务就可以让服务重新上线。

5.2.4 设置Eureka的服务实例状态

有时候我们下线服务实例之后, 需要在不重新部署服务实例的情况下,重新上线服务实例。此时就使用这种方式。

1、下线

接口方式如下

方法:PUT

接口:/eureka/apps/{appName}/{instanceId}/status?value=OUT_OF_SERVICE

举例,通过postman使用 PUT方法 访问 http://localhost:8761/eureka/apps/SERVICE-PRODVIDER1/192.168.0.106:service-prodvider1:8762/status?value=OUT_OF_SERVICE,如下:

Spring Cloud服务注册-Eureka介绍和部署

执行结果如下图,改实例状态变为OUT_OF_SERVICE

Spring Cloud服务注册-Eureka介绍和部署

2、 恢复上线

接口方式如下:

方法: DELETE

接口: /eureka/apps/{appName}/{instanceId}/status?value=UP

举例,通过postman使用 DELETE方法 访问

http://localhost:8761/eureka/apps/SERVICE-PRODVIDER1/192.168.0.106:service-prodvider1:8762/status?value=UP

Spring Cloud服务注册-Eureka介绍和部署

执行后的结果为,服务实例重新上线,状态为”UP”

Spring Cloud服务注册-Eureka介绍和部署

5.2.5 一个部署流程

比较优雅的一种服务部署流程方式有:

方式1 :可以通过”设置Eureka的服务实例状态”下线机器;执行部署脚本:kill 服务、重新部署服务;再通过”设置Eureka的服务实例状态”上线此实例。

方式2: 先调用实例的/shutdown接口,然后重新部署该服务

6 Eureka Server 集群搭建

Eureka单机房和双机房集群部署

转自:http://www.heartthinkdo.com/?p=1933

Original: https://www.cnblogs.com/fnlingnzb-learner/p/16458886.html
Author: Boblim
Title: Spring Cloud服务注册-Eureka介绍和部署

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540691/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球