前言

在分布式系统领域有个著名的CAP定理:

C——数据一致性;

A——服务可用性;

P——服务对网络分区故障的容错性。

这三个特性在任何分布式系统中不能同时满足,最多同时满足两个。

Zookeeper是著名Hadoop的一个子项目,很多场景下Zookeeper也作为Service发现服务解决方案。Zookeeper保证的是CP,即任何时刻对Zookeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。

而Spring Cloud Netflix在设计Eureka时遵守的就是AP原则。因为对于服务消费者来说,能消费才是最重要的——拿到可能不正确的服务实例信息后尝试消费一下,也好过因为无法获取实例信息而不去消费。所以,对于服务发现而言,可用性比数据一致性更加重要——AP胜过CP。

1、服务注册与服务发现

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

服务注册:服务治理框架会构建一个注册中心,每个服务向注册中心注册登记自己提供的服务,将服务名、主机、端口号、版本号、通信协议等告知注册中心,注册中心按服务名分类组织成一个服务清单。

例如:

有三个提供订单服务的实例分别运行在 192.168.0.100:8081、192.168.0.101:8082、192.168.0.102:8083;

还有四个提供用户服务的实例分别运行在 192.168.1.100:8091、192.168.1.101:8092、192.168.1.102:8093、192.168.1.103:8094;

当这些服务全部启动并成功注册到注册中心上后,注册中心会维护一份类似下面的一个服务清单:

服务名 服务地址
订单服务 192.168.0.100:8081、192.168.0.101:8082、192.168.0.102:8083
用户服务 192.168.1.100:8091、192.168.1.101:8092、192.168.1.102:8093、192.168.1.103:8094

服务发现:在服务治理框架下,服务之间不再通过具体实例地址来相互调用,而是通过向注册中心咨询并获取服务清单,以实现(通过服务名)对具体服务的调用。

  例如:前台用户下单需要调用订单服务,首先向注册中心发起咨询订单服务的请求,注册中心返回订单服务位置清单,然后调用方通过负载策略选择其中某一个位置进行服务调用即可。

2、单点注册中心

创建一个空项目,pom.xml如下(后面都基于这个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.springcloud.demo</groupId>
<artifactId>springcloud-demo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server</module>
<module>eureka-service-provider</module>
</modules> <name>Maven</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org/</url>
<inceptionYear>2001</inceptionYear> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
<relativePath/>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties> <dependencies>
<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>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<failIfNoTests>true</failIfNoTests>
</configuration>
</plugin>
</plugins>
</build>
</project>

1、服务注册中心

首先搭建一个注册中心,命名为eureka-server,引入eureka依赖包

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

在 Spring Boot 启动入口文件上加注解 @EnableEurekaServer

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

然后配置application.yml:

server:
port: 8081 eureka:
instance:
hostname: eurekaserver
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ spring:
application:
name: eurka-server

其中:

eureka.client.registerWithEureka = false     设置为false表示不向注册中心注册自己,默认为true
eureka.client.fetchRegistry = false               设置为false表示不需要去检索服务,默认为true

启动应用并访问 http://localhost:8081/ ,如下图所示:

可以看到注册中心还没有注册任何服务,至此注册中心已经搭建完毕。

2、服务提供者

搭建好注册中心后,我们再来创建一个服务提供者,然后将其注册到注册中心。新建一个项目eureka-service-provider,添加eureka依赖,在 Spring Boot 启动入口文件上加注解 @EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run( EurekaServiceApplication.class, args );
}
}

配置application.yml:

server:
port: 8082 eureka:
instance:
hostname: service-provider
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/ spring:
application:
name: service-1

因为需要向注册中心注册,所以 eureka.client.registerWithEureka、eureka.client.fetchRegistry 不要配置为 false

启动eureka-service-provider,刷新注册中心,可以看到服务已经注册成功了:

同时eureka-server控制台会打印一行日志:Registered instance SERVICE-1/xxxx:service-1:8082 with status UP (replication=false)

3、高可用注册中心

上面只是一个单点注册中心,微服务场景下应用通过注册中心来访问真实服务,如果注册中心挂了会造成服务无法调用,所以注册中心也得要保持高可用,Eureka 不可能没有想到这一点,其实在Eureka里,所有结点既是服务提供方,又是服务消费方,注册中心也不例外。

大家还记得在单节点配置里讲到的这两个配置吗:

eureka.client.registerWithEureka = false

eureka.client.fetchRegistry = false

实际上 Eureka 高可用方案就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组相互注册的服务注册中心,在这组服务注册中心内部相互同步注册清单,形成一个高可用集群

注册中心集群

创建以下三个Eureka Server:peer1、peer2、peer3

peer1的配置如下(peer2、peer3配置类似):

server:
port: 8081 eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2:8082/eureka/,http://peer3:8083/eureka/ spring:
application:
name: eurka-server

分别启动peer1、peer2、peer3,访问peer1:8081

单点故障

这时候如果peer2突然挂了,访问peer1和peer3仍然可以看到peer2,这是因为Eureka默认开启了自我保护机制(peer2挂了没有剔除),可以通过设置 eureka.server.enable-self-preservation=false 来禁用保护

peer1的配置文件里新增eureka.server.enable-self-preservation=false设置,然后模拟peer3挂了,peer1注册中心如下:

大概两分钟左右,从peer1注册中心可以看到 registered-replicas 有3个,unavailable-replicas 里有 peer3,available-replicas 里只有 peer1 和 peer2 可用,

而从 peer2 里看 peer3 仍然可用(过比较长的时间,peer2 仍然会将 peer3 从 available-replicas 里剔除)

将serverce-1注册到注册中心peer1,然后在peer1 和 peer2里都可以看到service-1。

故障恢复

peer3 经过运维处理恢复了,重新启动peer3自动加入了peer1和peer2集群,可用看到service-1也自动注册到peer3上了:

4、配置

服务注册相关配置:eureka.instance 为前缀对应的Class

org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean

服务实例相关配置:eureka.client 为前缀对应的Class

org.springframework.cloud.netflix.eureka.EurekaClientConfigBean

服务配置属性以eureka.server为前缀对应的Class

org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean

client常见配置

# 启用Eureka客户端
eureka.client.enabled=true
# 从Eureka服务端获取注册信息的间隔时间(单位:秒)
eureka.client.registry-fetch-interval-seconds=30
# 是否从Eureka服务端获取注册信息
eureka.client.fetch-registry=true
# 是否要将自身的实例信息注册到Eureka服务端
eureka.client.register-with-eureka=true
# 初始化实例信息的变化到Eureka服务端的间隔时间(单位:秒)
eureka.client.instance-info-replication-interval-seconds=40
# 从Eureka客户端到Eureka服务端的连接总数
eureka.client.eureka-server-total-connections=200
# 获取实例时是否过滤,仅保留UP状态的实例
eureka.client.filter-only-up-instances=true

server常见配置

#设为false,关闭自我保护
eureka.server.enable-self-preservation=false
#表示是否将自己注册到Eureka Server,默认为true
eureka.client.register-with-eureka=false
#表示是否从Eureka Server获取注册信息,默认为true
eureka.client.fetch-registry=false
# 扫描失效服务的间隔时间(单位毫秒,默认是60*1000)即60秒
eureka.server.eviction-interval-timer-in-ms=5000
#设置 eureka server同步失败的等待时间 默认 5分
#在这期间,它不向客户端提供服务注册信息
eureka.server.wait-time-in-ms-when-sync-empty=5
#设置 eureka server同步失败的重试次数 默认为 5 次
eureka.server.number-of-replication-retries=5
#自我保护系数(默认0.85)
eureka.server.renewal-percent-threshold=0.85

instance常见配置

#是否优先使用IP地址作为主机名的标识,如果不配置就是机器的主机名
eureka.instance.prefer-ip-address=false
#Eureka客户端向服务的发送心跳的时间间隔(单位:秒)
eureka.instance.lease-renewal-interval-in-seconds=30
#Eureka服务的收到最后一次心跳之后等待的时间上限(单位:秒),
#超过这个时间之后会将该服务实例从注册中心清单里剔除
eureka.instance.lease-expiration-duration-in-seconds=90

附录

  本文Demo地址

  Spring Cloud Netflix官方文档

  Spring Cloud 中文社区

  spring-cloud-book

服务治理

SpringCloudLesson

更多配置参考

spring cloud 服务治理 - Eureka的更多相关文章

  1. Spring Cloud 系列之 Eureka 实现服务注册与发现

    如果你对 Spring Cloud 体系还不是很了解,可以先读一下 Spring Cloud 都有哪些模块 Eureka 是 Netflix 开源的服务注册发现组件,服务发现可以说是微服务架构的核心功 ...

  2. spring cloud 服务注册中心eureka高可用集群搭建

    spring cloud 服务注册中心eureka高可用集群搭建 一,准备工作 eureka可以类比zookeeper,本文用三台机器搭建集群,也就是说要启动三个eureka注册中心 1 本文三台eu ...

  3. Spring Cloud服务的注册与发现(Eureka)

    一.spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选.分布式会话等等.它运 ...

  4. spring Cloud服务注册中心Eureka集群

    spring Cloud服务注册中心Eureka集群配置: 在application.yml文件加以下配置: server: port: 8761 tomcat: uri-encoding: UTF- ...

  5. 基于Spring cloud Ribbon和Eureka实现客户端负载均衡

    前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...

  6. 老板让我重构项目,我想首先应该服务治理---eureka服务治理深入浅出

    目录 什么是服务治理 Eureka调用过程 Eureka单机注册 Eureka 单机启动 单机注册 集群注册 客户调用 Eureka集群注册 idea 如何同一个项目启动多次 Eureka自我保护 为 ...

  7. Spring Cloud 服务端注册与客户端调用

    Spring Cloud 服务端注册与客户端调用 上一篇中,我们已经把Spring Cloud的服务注册中心Eureka搭建起来了,这一章,我们讲解如何将服务注册到Eureka,以及客户端如何调用服务 ...

  8. spring cloud config与eureka配合使用

    前面两篇介绍了Spring Cloud Config服务端和客户端的简单配置,本篇介绍Spring Cloud Config与Eureka配合使用 前言 默认情况下,配置客户端启动时,都是通过配置属性 ...

  9. Spring Cloud 入门 之 Eureka 篇(一)

    原文地址:Spring Cloud 入门 之 Eureka 篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Cloud 是一系列框架的有序集合.它利用 Sp ...

随机推荐

  1. 微信页面script标签添加crossorigin=“anonymous”导致页面加载失败

    公司一个微信企业号项目,突然出现页面数据加载失败,页面报错信息如下 意思是前端向服务端发送跨域资源请求访问这个js文件,但是服务端并不同意,所以服务端拒绝访问这个地址. 后来发现将crossorigi ...

  2. 2019 企叮咚java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.企叮咚等公司offer,岗位是Java后端开发,因为发展原因最终选择去了企叮咚,入职一年时间了,也成为了面试官 ...

  3. 使用electron在mac升级签名后进行升级出现“QRLUpdaterErrorDomain”的错误

    现在在开发electron客户端,windows签名使用了签名狗的方式进行签名(小坑:签名狗只能对打包完的exe进行签名,而electron-builder需要在打包的时候将证书配置进去,所以需要导出 ...

  4. android studio学习----创建模拟器

    建议在创建模拟器前把 SDK Manager 中的 Tools.Extras 都更新到最新. 如何弹出下面的各个图,首先直接点击  运行  然后会选择  launcher ,点击那个 ...就出来了 ...

  5. 更改用户host留下的坑

    前言:  我们在创建数据库用户的时候都会指定host,即一个完整的用户可描述为 'username'@'host' .创建用户时不显式指定host则默认为%,%代表所有ip段都可以使用这个用户,我们也 ...

  6. Linux源码编译nginx

    1.安装nginx 安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel 首先要安装 ...

  7. docker在linux上的安装

    docker安装在liunx环境上,我电脑用的是ubuntu系统的,需要下载对应系统的docker,我下载的是社区版,对着官方的命令敲就好了, 地址是:https://docs.docker.com/ ...

  8. eclipse activiti 不能自动生成png图片解决方案

    1. Windows-->Preferences 2. Activiti-->Save Actions-->勾选 Create process definition ... --&g ...

  9. Winform 弹框增加确定按钮并点击确定后进行下一步操作

    //审核完毕后调用打印 MessageBoxButtons messButton = MessageBoxButtons.OKCancel; DialogResult dr = MsgBox.Show ...

  10. university-conda

    1.建立环境 conda create -n djx python=3.7 2.激活 conda activate djx 3.退出 conda deactivate 4.查看 conda env l ...