程序员社区

SpringCloud构建微服务之Eureka服务注册与发现

前言

在上篇文章我讲到如何搭建SpringCloud微服务基础环境,本次我将介绍NetflixEureka,并整合到SpringCloud

什么是Eureka?

EurekaNetflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。功能类似于dubbo的注册中心,比如Zookeeper

Netflix在设计Eureka时遵守的就是AP原则

CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得

下面我们就来撸代码啦~

建立Eureka注册中心(spring-cloud-eureka)

首先建立一个Eureka父工程(spring-cloud-eureka))(此父工程非必需,看个人的工程层次结构的划分),此处建立是便于知识点划分

选中父工程(spring-cloud-examples`)鼠标点击右键File → Module → Maven
不用勾选任务任何选项,直接Next → Finish
在这里插入图片描述

创建好后,删除src目录,并选中spring-cloud-eureka工程,创建此工程的子模块eureka
选中父工程(spring-cloud-eureka)鼠标点击右键File → Module → Maven
不用勾选任务任何选项,直接Next → Finish
在这里插入图片描述
创建好后,修改eureka工程的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">
    <parent>
        <artifactId>spring-cloud-eureka</artifactId>
        <groupId>com.chaytech</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka</artifactId>

    <dependencies>
        <!--eureka-server服务端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
</project>

创建application.yml

server:
  port: 7001

eureka:
  instance:
    hostname: localhost #eureka服务端的实例名称
  client:
    register-with-eureka: false #false表示不向注册中心注册自己。
    fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。

启动类

@SpringBootApplication
// EurekaServer服务器端启动类,接受其它微服务注册进来
@EnableEurekaServer
public class EurekaServer7001_Application {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer7001_Application.class, args);
    }
}

启动eureka工程,测试
浏览器中访问:http://localhost:7001/

显示页面
在这里插入图片描述
ok,eureka注册中心已成功搭建!

但是细心的人可以发现页面中显示No application available 翻译成中文的意思是:没有服务被发现

因为没有注册服务进来当然不可能有服务被发现,下面将介绍如何将服务注册到eureka

上面步骤完成后看看结构是不是和我这一样呢?
最终工程展现
在这里插入图片描述

将已有的(spring-cloud-provider-user)用户微服务注册进eureka

不要慌,服务注册不是很复杂,只需小改代码和配置文件即可
修改spring-cloud-provider-user的pom文件
增加如下内容

<!-- 将微服务provider侧注册进eureka -->
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-eureka</artifactId>
   </dependency>
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-config</artifactId>
   </dependency>

修改后的完整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">
    <parent>
        <artifactId>spring-cloud-examples</artifactId>
        <groupId>com.chaytech</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-cloud-provider-user</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.chaytech</groupId>
            <artifactId>spring-cloud-model</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 将微服务provider侧注册进eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <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>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
</project>

修改application.yml文件
增减如下内容

eureka:
  client: #客户端注册进eureka服务列表内
    service-url:
      defaultZone: http://localhost:7001/eureka

修改后的完整application.yml文件

server:
  port: 8001

mybatis:
  config-location: classpath:mybatis/mybatis-config.xml        # mybatis配置文件所在路径
  type-aliases-package: com.chaytech.model.*    # 所有Entity别名类所在包
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件

spring:
   application:
    name: user-provider
   datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包
    url: jdbc:mysql://127.0.0.1:3306/spring_cloud_db01              # 数据库名称
    username: root
    password: root
    dbcp2:
      min-idle: 5                                           # 数据库连接池的最小维持连接数
      initial-size: 5                                       # 初始化连接数
      max-total: 5                                          # 最大连接数
      max-wait-millis: 200                                  # 等待连接获取的最大超时时间

eureka:
  client: #客户端注册进eureka服务列表内
    service-url:
      defaultZone: http://localhost:7001/eureka

修改spring-cloud-provider-user服务启动类,增加@EnableEurekaClient注解,此注解代表此服务是eureka客户端,并将此服务注册进eureka服务中

@SpringBootApplication
// 本服务启动后会自动注册进eureka服务中
@EnableEurekaClient
public class UserProvider8001_Application {

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

测试
要先启动EurekaServer也是前面建立的eureka工程,再启动spring-cloud-provider-user
再次访问:http://localhost:7001/
在这里插入图片描述
可以看到此时没有No application available提示了,有服务注册进来了

此处注意了,列表Application列显示的名称就是我们在配置文件中配置的spring.application.name
在这里插入图片描述
在这里插入图片描述
然后再看列表最后面的Status列,数据是带超链接的,点击可以跳转,但此时点击显示Error Page
在这里插入图片描述
这个info是SpringBoot内置的restful api请求,用来显示任意的应用信息,因为没有配置所以会跳转到Error Page页面,下面咱们来配置一下。

spring-cloud-provider-userpom文件中引入actuaotrjar包,新增如下内容

 <!-- actuaotr服务监控-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
 </dependency>

如果需要通过info接口来获取maven中的属性内容需要在父工程(spring-cloud-examples)添加如下配置

    <build>
        <finalName>spring-cloud-examples</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <delimiters>
                        <delimit>$</delimit>
                    </delimiters>
                </configuration>
            </plugin>
        </plugins>
    </build>

修改application.yml文件,增加info信息

info:
  app.name: user-provider
  build.artifactId: $project.artifactId$
  build.version: $project.version$

重新build整个微服务工程 ,重启服务,再次访问
在这里插入图片描述
可以看到返回了一个json串,内容就是我们在application.yml中配置的

eureka自我保护

在前面我们介绍eureka的时候有说到eureka是AP的,那就说明他又一定的容错机制,也就是指的eureka有自我保护机制。
下面我们来做一下实验,启动eureka服务端和服务提供者,然后将服务提供者停掉,等几分钟访问http://localhost:7001/ 看看会出现什么
如果不出意外的话,会出现如下图所示
在这里插入图片描述
这是eureka给的警告提示,由于spring-cloud-provider-user服务注册到eureka之后,我们将服务停掉了,也就没有再给eureka发送心跳了,这个时候eureka不会立刻清理,依旧会对该微服务的信息进行保存。

默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,EurekaServer就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。

在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

在Spring Cloud中,可以使用eureka.server.enable-self-preservation = false配置禁用自我保护模式。

赞(0) 打赏
未经允许不得转载:IDEA激活码 » SpringCloud构建微服务之Eureka服务注册与发现

一个分享Java & Python知识的社区