SpringCloud服务注册与发现(Eureka)

作者:xcbeyond
疯狂源自梦想,技术成就辉煌!微信公众号:《程序猿技术大咖》号主,专注后端开发多年,拥有丰富的研发经验,乐于技术输出、分享,现阶段从事微服务架构项目的研发工作,涉及架构设计、技术选型、业务研发等工作。对于Java、微服务、数据库、Docker有深入了解,并有大量的调优经验。












0、前言
      微服务是近两年比较火的概念,被称为程序员必备技能之一了,可见其运用之广。最近整理下资料进行系统的学习,与大家一一分享。

       微服务是相对于传统单体式架构而言的。单体式架构是一份代码,部署都是基于单个单元进行的,它的优点是易于部署,但面临的就是可用性低、可伸缩性差。微服务的出现解决了这个问题,它以单独的服务来做一个功能,因此,每个单独的功能被称为一个服务,各个服务之间可以相互调用。

(微服务更多了解请参看微服务介绍)

        本章节主要讲解各个服务之间是如何进行相互调用的,即:SpringCloud Eureka,它是云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。

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

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

Eureka服务治理体系如下:

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

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

1.2 Eureka
1.2.1 Eureka介绍
       Spirng Cloud Eureka使用Netflix Eureka来实现服务注册与发现。它既包含了服务端组件,也包含了客户端组件,并且服务端与客户端均采用java编写,所以Eureka主要适用于通过java实现的分布式系统,或是JVM兼容语言构建的系统。Eureka的服务端提供了较为完善的REST API,所以Eureka也支持将非java语言实现的服务纳入到Eureka服务治理体系中来,只需要其他语言平台自己实现Eureka的客户端程序。目前.Net平台的Steeltoe、Node.js的eureka-js-client等都已经实现了各自平台的Ereka客户端组件。

1.2.2 Eureka服务端
      Eureka服务端,即服务注册中心。它同其他服务注册中心一样,支持高可用配置。依托于强一致性提供良好的服务实例可用性,可以应对多种不同的故障场景。

       Eureka服务端支持集群模式部署,当集群中有分片发生故障的时候,Eureka会自动转入自我保护模式。它允许在分片发生故障的时候继续提供服务的发现和注册,当故障分配恢复时,集群中的其他分片会把他们的状态再次同步回来。集群中的的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例关于所有服务的状态可能存在不一致的现象。

1.2.3 Eureka客户端
         Eureka客户端,主要处理服务的注册和发现。客户端服务通过注册和参数配置的方式,嵌入在客户端应用程序的代码中。在应用程序启动时,Eureka客户端向服务注册中心注册自身提供的服务,并周期性的发送心跳来更新它的服务租约。同时,他也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期行的刷新服务状态。

2、服务注册中心(Eureka服务端)
2.1 注册中心项目构建
2.1.1 新建模块化项目父项目
(SpringCloud系列教程的工程j将以Maven模块化项目方式创建,便于各个微服务的项目管理。)

父项目并不是创建注册中心所必须的,只是为了方便后续各个服务工程的管理。

(1)与新建一般SpringBoot项目一样,请参考【SpringBoot 系列】一、SpringBoot项目搭建。

       新建名为“springCloud”项目作为父项目,项目结构如下图:

(2)修改添加pom.xml配置及SpringCloud依赖包。

 ①  将packaging标签值修改为pom。(如果不修改添加,则无法添加子项目),如下:

    <groupId>com.xcbeyond.springcloud</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>springCloud</name>
    <url>http://maven.apache.org</url>
②添加SpringCloud的依赖包:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath/>
</parent>
③添加dependency对所有子模块都是有效的,即:在子模块中不用再额外添加这些依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
 
    <dependency>
           <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>
(3)使用modules标签实现模块化项目管理 。

        在pom.xml中添加modules标签,引入服务发现springCloudEureka项目,如下:

<!-- 使用modules标签实现模块化项目管理 -->
<modules>
    <!-- 服务发现。 (Eureka Server)-->
    <module>springCloudEureka</module>
</modules>
或者在pom.xml的Overview视图中,【Modules】选项中直接进行“添加”或“创建”子项目。如下图:

pom.xml完整配置如下:

<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.xcbeyond.springcloud</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>springCloud</name>
    <url>http://maven.apache.org</url>
 
    <!-- 使用modules标签实现模块化项目管理 -->
    <modules>
        <!-- 服务发现。 (Eureka Server)-->
        <module>springCloudEureka</module>
    </modules>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>
2.1.2 新建Eureka服务注册中心子项目
(1)新建springCloudEureka项目作为Eureka注册中心,如下图:

(2)pom.xml中添加依赖包。

注册中心依赖于Eureka Server,所以需要添加以下依赖:

<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>
        <version>2.0.0.RELEASE</version>
    </dependency>
</dependencies>
2.2 Eureka服务注册中心代码实现及配置
(1)springCloudEureka启动类。

com.xcbeyond.springcloud.eureka.SpringCloudEureka.java

(这是一个常规的SpringBoot项目,启动类只需额外使用@EnableEurekaServer注解开启对对EurekaServer的支持)

package com.xcbeyond.springcloud.eureka;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 
/**
 * Eureka启动类
 * @author xcbeyond
 * 2018年8月3日上午9:40:48
 */
@SpringBootApplication
//开启对EurekaServer的支持,即:作为Eureka服务端
@EnableEurekaServer
public class SpringCloudEureka {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudEureka.class, args);
    }
}
(2)配置application.properties,如下:

#当前Eureka服务器端口
server.port=8761
#服务注册中心实例的主机名
eureka.instance.hostname=localhost
#是否向服务注册中心注册自己
eureka.client.registerWithEureka=false
#是否检索服务
eureka.client.fetchRegistry=false
2.3、启动Eureka
        运行springCloudEureka项目的启动类SpringCloudEureka,启动成功后,访问http://localhost:8761/,可以看到Eureka的信息面板,如下图,则表明Eureka启动配置成功。

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

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

       Eureka客户端实质是代表一个服务,用来完成具体的业务功能模块。

3.2 创建Eureka客户端项目
  按照 “2.1.2 新建Eureka服务注册中心子项目”的方式创建Eureka客户端项目springCloudEurekaClient,如下:

3.3 导入依赖包
     pom.xml如下:

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
 
    <parent>
        <groupId>com.xcbeyond.springcloud</groupId>
        <artifactId>springCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    
    <groupId>com.xcbeyond.springcloud</groupId>
    <artifactId>springCloudEurekaClient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <name>springCloudEurekaClient</name>
    <url>http://maven.apache.org</url>
    <description>服务提供者。</description>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </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>
            <version>2.0.0.RELEASE</version>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
3.4 Eureka客户端代码实现及配置
(1)启动类实现

com.xcbeyond.springcloud.eurekaclient.EurekaClientApplication.java

package com.xcbeyond.springcloud.eurekaclient;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
/**
 * Eureka Client(服务提供者)启动类
 * @author xcbeyond
 * 2018年8月3日下午3:05:44
 */
@SpringBootApplication
//开启作为Eureka Server的客户端的支持
@EnableEurekaClient
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}
(2)application.properties如下:

(/springCloudEurekaClient/src/main/resources/application.properties)

#当前服务器端口
server.port=8001
#应用名
spring.application.name=Eureka-Client
 
#服务注册中心地址,需按照注册中心IP进行对应修改
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
3.5启动Eureka客户端
 运行启动类EurekaClientApplication,启动完成后,访问Eureka信息面板http://localhost:8761/,发现Instancescurrently registered with Eureka一栏显示EUREKA-CLIENT已经注册成功,如下图: