Spring Cloud Eureka 服务注册与发现

一、 Eureka服务治理体系

1.1、服务治理

服务治理是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册和发现。

Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它基于Netflix Eureka做了二次封装。主要负责完成微服务架构中的服务治理功能。

1、官网地址: https://projects.spring.io/spring-cloud/
2、Eureka由两个组件组成:

Eureka Server(服务注册中心)
Eureka Client(服务发现)

3、Eureka 服务治理体系如下:
这里写图片描述

1.2、服务注册

在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,包括服务的主机与端口号、服务版本号、通讯协议等一些附加信息。注册中心按照服务名分类组织服务清单,同时还需要以心跳检测的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,以达到排除故障服务的效果。

1.3、服务发现

在服务治理框架下,服务间的调用不再通过指定具体的实例地址来实现,而是通过服务名发起请求调用实现。服务调用方通过服务名从服务注册中心的服务清单中获取服务实例的列表清单,通过指定的负载均衡策略取出一个服务实例位置来进行服务调用。

二、服务注册中心(Eureka Server)

2.1、服务注册中心功能概述

在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,包括服务的主机与端口号、服务版本号、通讯协议等一些附加信息。注册中心按照服务名分类组织服务清单,同时还需要以心跳检测的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,以达到排除故障服务的效果。

2.2、创建Eureka Server 服务

1、IDEA,新建一个Spring Initializr项目:
这里写图片描述

这里写图片描述

2、勾选Web、Eureka Server模块:
这里写图片描述
3、创建完成:
这里写图片描述

4、POM文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fxbin</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5、编辑application.yml配置文件内容如下:

server:
  port: 8761
spring:
  profiles:
    active: dev
eureka:
  server:
    # 是否开启自我保护,默认为 true, 在开启自我保护的情况下,注册中心在丢失客户端时,
    # 会进入自动保护模式,注册中心并不会将该服务从注册中心删除掉 , 如果设置为 true,在负载均衡条件下,一个服务挂掉后,注册中心并没有删掉该服务,
    # 会导致客户端请求的时候可能会请求到该服务,导致系统无法访问
    enable-self-preservation: false
  instance:
    # 是否以 IP 注册到注册中心,Eureka 默认是以 hostname 来注册的。
    prefer-ip-address: true
    hostname: ${spring.cloud.client.ip-address}
    instance-id: ${spring.cloud.client.ip-addres}:${server.port}
  client:
    # #是否向服务注册中心注册自己
    register-with-eureka: false
    # #是否检索服务
    fetch-registry: false
    service-url:
      # 注册中心默认地址。
      default-zone: http://${eureka.instance.hostname}:${server.port}/eureka/

注:由于server和client是采用心跳机制来确认存活的,所以在启动项目的过程可能依旧会报错。但是只要启动后不是一直报错,并且能正常访问Eureka信息面板页面的话,则代表项目是在正常运行的

6、通过@EnableEurekaServer注解启动服务注册中心,如下:

package com.fxbin.eurekaserver;

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

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

三、服务提供(发现)者(Eureka Client)

3.1、服务注册

服务提供者在启动的时候会通过REST请求的方式将自己注册到Eureka Server上,同时带上自身服务的一些元数据信息。Eureka Server接收到这个Rest请求之后,将元数据信息存储在一个双层结构的Map中,其中第一层的key是服务名。第二层的key 是具体服务的实例名。

在服务注册时,需要确认一下eureka.client.register-with-eureka=true参数是否正确,该值默认为true。若设置为fasle将不会启动注册操作。

3.2、服务同步

从eureka服务治理体系架构图中可以看到,不同的服务提供者可以注册在不同的服务注册中心上,它们的信息被不同的服务注册中心维护。

此时,由于多个服务注册中心互相注册为服务,当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发给集群中相连的其他注册中心,从而实现服务注册中心之间的服务同步。通过服务同步,提供者的服务信息就可以通过集群中的任意一个服务注册中心获得。

3.3、服务续约

在注册服务之后,服务提供者会维护一个心跳用来持续高速Eureka Server,“我还在持续提供服务”,否则Eureka Server的剔除任务会将该服务实例从服务列表中排除出去。我们称之为服务续约。

下面是服务续约的两个重要属性:

(1)eureka.instance.lease-expiration-duration-in-seconds

leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance。

默认为90秒
如果该值太大,则很可能将流量转发过去的时候,该instance已经不存活了。
如果该值设置太小了,则instance则很可能因为临时的网络抖动而被摘除掉。
该值至少应该大于leaseRenewalIntervalInSeconds
(2)eureka.instance.lease-renewal-interval-in-seconds

leaseRenewalIntervalInSeconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外,如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量。

默认30秒

3.4、创建Eureka Client 服务

1、IDEA,新建一个Spring Initializr项目:
这里写图片描述
这里写图片描述
2、勾选Web、Eureka Discovery模块:
这里写图片描述
3、创建完成
这里写图片描述

4、POM文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fxbin</groupId>
    <artifactId>eureka-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-client</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5、编辑application.yml配置文件内容如下:

server:
  port: 8763
spring:
  application:
    name: eureka-client

eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka/

6、通过@EnableEurekaClient注解启动服务注册中心,如下:

package com.fxbin.eurekaclient;

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

@EnableEurekaClient  //服务提供者
@SpringBootApplication
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

四、启动服务注册中心与服务提供者

上述配置完成之后,我们分别启动注册中心,服务提供者,浏览器访问 http://localhost:8761
即可看到如下所示:
这里写图片描述

4.1、Eureka的高可用

考虑到发生故障的情况,服务注册中心发生故障必将会造成整个系统的瘫痪,因此需要保证服务注册中心的高可用。

Eureka Server在设计的时候就考虑了高可用设计,在Eureka服务治理设计中,所有节点既是服务的提供方,也是服务的消费方,服务注册中心也不例外。

Eureka Server的高可用实际上就是将自己做为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。

即在多节点集群情况下,使Eureka Server 相互注册对方,这样在单节点故障的情况下,依旧可以维持服务的可用:

下面以三个节点配置为例:

1、Eureka Server 配置
server1配置

spring:
  application:
    name: eureka-server
  profiles: discovery1
server:
  port: 8761
eureka:
  instance:
    hostname: discovery1
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 30
    prefer-ip-address: true
  client:
    service-url:
      default-zone: http://discovery2:8762/eureka/, http://discovery3:8763/eureka/
    fetch-registry: true
    register-with-eureka: true

server2配置

spring:
  application:
    name: eureka-server
  profiles: discovery2
server:
  port: 8762
eureka:
  instance:
    hostname: discovery2
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 30
    prefer-ip-address: true
  client:
    service-url:
      default-zone: http://discovery1:8761/eureka/, http://discovery3:8763/eureka/
    fetch-registry: true
    register-with-eureka: true

server3配置

spring:
  application:
    name: eureka-server
  profiles: discovery3
server:
  port: 8763
eureka:
  instance:
    hostname: discovery3
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 30
    prefer-ip-address: true
  client:
    service-url:
      default-zone: http://discovery1:8761/eureka/, http://discovery2:8762/eureka/
    fetch-registry: true
    register-with-eureka: true

注: 一定要修改hosts 配置文件,因为以上配置指定 分别指定了三个服务的 hostname

2、Eureka Client 配置:

server:
  port: 8787
spring:
  application:
    name: eureka-client  
eureka:
  client:
    service-url:
      default-zone: http://discovery1:8761/eureka/,http://discovery2:8762/eureka/,http://discovery3:8763/eureka/
4.2、 失效剔除

有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障等原因使服务不能正常运作。而服务注册中心并未收到“服务下线”的请求,为了从服务列表中将这些无法提供服务的实例剔除,Eureka Server在启动的时候会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除出去。

                                -- 完--
如有不妥之处,敬请告知,谢谢
posted @ 2018-08-13 05:04  大痴小乙  阅读(335)  评论(0)    收藏  举报