什么是Spring Cloud Eureka

Spring Cloud Eureka 是 Spring Cloud 中的一个组件,它是基于 Netflix Eureka 做了二次封装,主要是负责完成微服务框架中服务治理的功能。Spring Cloud通过为 Eureka 增加了 Spring Boot 风格的自动化配置,我们只需要通过简单的引用依赖和注解就能让 Spring Boot 够将的微服务应用轻松的与 Eureka 服务治理体系进行整合。

服务治理

服务治理是微服务框架中最为核心和基础的模块,它主要是用来实现各个微服务实例的自动化注册与发现。
最初开始,可能构建的微服务系统服务并不是很多,我们可以通过一些静态配置来完成服务的调用。比如有两个服务 A 和 B,其中 A 服务需要调用 B 服务来完成一个业务操作时,为了实现 B 服务的高可用,无论我们采用服务端的复杂均衡,还是客户端的负载均衡,我们都需要手工的来维护一份 B 的实例列表。但是随着业务的发展,系统功能越来越复杂,相应的微服务也是越来越多,这种静态手工维护的难度会越来越高。
为了解决这种问题,产生了大量的服务治理的框架和产品。这些框架其实都是围绕着服务注册和服务发现机制来完成对微服务应用实例的自动化管理。

  • 服务注册

在服务治理框架中,通常都会构建一个服务注册中心,每个服务实例单元向注册中心登记自己的服务,将实例主机位置、端口号、版本号、通信协议等一系列附加信息告诉注册中心,注册中心按服务名分类组织服务清单。

  • 服务发现

由于在服务治理框架下操作,服务间的通信与调用不再是通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。所以,服务调用方在调用服务提供方的接口时,并不知道具体的服务实例位置。因此,需要先向注册中心发起查询请求,获取实例清单,以实现对具体服务实例的访问。

搭建 Eureka 注册中心服务

搭建单中心 Eureka

  • Spring Cloud 版本:Finchley.BUILD-SNAPSHOT
  • Spring Boot 版本:2.0.2.RELEASE

我们之后的所有开发都会基于以上版本进行操作,需要注意的是:Sring Cloud 使用的是 SNAPSHOT 版,所以需要在 pom 文件中指定仓库的地址。
首先,我们新建一个 Spring Boot 工程,命名为:spring-cloud-eureka,并在 pom 中添加必要的依赖,具体 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.sagesource</groupId>
    <artifactId>spring-cloud-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-cloud-eureka</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.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.BUILD-SNAPSHOT</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>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

通过 @EnableEurekaServer 注解启动一个服务注册中心提供给其他应用进行对话。这一步非常简单,只需在一个普通的 Spring Boot 应用中添加这个注解就能开启此功能:

@SpringBootApplication
@EnableEurekaServer
public class ApplicationEurekaServer {

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

}

在默认的配置下,注册中心服务端也会将自己作为一个客户端来注册自身,一般情况下,我们需要禁用这个功能,修改后的 application.yml 如下:

# spring config
spring:
  application:
    name: spring-boot-eureka

# server config
server:
  port: 9871

# eureka config
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false #不向注册中心注册自己
    fetch-registry: false #不检索服务
    service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

由于我们都是在本地运行,为了后续的服务区分,我们将服务注册中心的端口通过 server.port 设置运行端口为:9871
在完成上述配置后,启动应用并访问 http://localhost:9871。可以看到如下页面,其中 Instance currently registered with Eureka 的列表是空的,说明还没有服务注册到该注册中心。

clipboard.png
我想大家都注意到上面那两行醒目的红字:

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.

原因:自我保护机制。Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server会将当前的实例注册信息保护起来,同时提示这个警告。
由于在单机情况下很容易出现该问题,按照网上的配置关闭掉自我保护后,Eureka 仍会报警,提示安全模式关闭,无法保证实例正确性。所以,我们暂时忽略该问题,后期集群部署时即可解决。

注册服务提供者

在完成了注册中心服务的搭建后,接下来我们可以尝试将一个既有的 Spring Boot 应用加入到Eureka 的服务治理体系中去。
我们仍然以之前的 spring-cloud-server 为例,我们只需要修改 application.yml以下配置:

# 应用名称
spring:
  application:
    name: spring-cloud-server

# eureka 注册中心位置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9871/eureka/

修改完成后,即可启动服务,这时我们在刷新 eureka 的管理页面,看到Instance currently registered with Eureka的列表信息如下:

clipboard.png
这表明,我们的服务已经成功注册在注册中心。

相关实例代码:https://github.com/sagesource...


薛定饿
96 声望8 粉丝

引用和评论

0 条评论