服务治理-Spring Cloud Eureka

版本信息

  • Spring Boot(1.5.19)
  • Spring Cloud (Edgware.SR5)

服务发现简介

服务发现旨在解决硬编码提供服务地址的问题,想解决这个问题,需要一个强大的服务发现机制,通过这种机制可以获取到服务提供者的网络信息,即使服务提供者的信息发生变化,服务消费者也无需修改配置文件,即通过服务发现组件实现微服务实例的自动化注册与发现。

服务提供者、服务消费者、服务发现组件关系:

  • 各个微服务启动时,将自己的网络地址等信息注册到服务发现组件,服务发现组件存储这些信息
  • 服务消费者从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者接口
  • 各个微服务与服务发现组件使用一定的机制(例如心跳)通信,服务发现组件若长时间没有和某个微服务通信,就会注销该实例
  • 微服务网络地址发生变更时,会重新注册到服务发现组件,服务消费者无需人工修改提供者的网络地址。

综上,服务发现组件具备以下功能:

  • 服务注册表:服务发现组件核心,记录各个微服务的信息,如服务名称、IP、端口等,并提供查询API(查询已注册到注册中心的可用微服务实例)和管理API(用于服务的注册和注销)。
  • 服务注册与发现:服务注册指微服务启动时,将自己的信息注册到服务发现组件;服务发现指查询可用为微服务列表及其网络地址的机制
  • 服务检查:通过一定的机制检测已注册的服务,如发现某个实例长时间无法访问,则从注册表中移除

Spring Cloud提供了多种服务发现组件,如Eureka、Consul和Zookeeper等,下边我们将讲解其中的Eureka组件,其它的组件大家可以从官网文档或网络上的博客文章中学习下。

Eureka简介

Spring Cloud Eureka是Spring CLoud Netflix微服务套件中的一部分,是基于Netflix Eureka的二次封装,主要完成微服务建构中的服务治理功能,其本身是一个基于REST的服务。

Spring Cloud Netflix中还包括Ribbon、Hystrix、Fegin和Zuul等,这些组件将在后续的连载文章中介绍

Eureka原理

Eureka官网架构图:
Eureka官网架构图
概念说明:

  • Application Service 服务提供者
  • Application Client 服务消费者
  • Make Remote Call 理解成调用RESTful API的行为
  • us-east-1c、us-east-1d、等都是zone,属于us-east1这个region

Region和Zone是AWS(Amazon Web Services)的概念,Region标识AWS中的地理位置,每个Regioin包含多个Zone,各个Region之间完全隔离,AWS通过这种方式实现最大的容错和稳定性。

SpringCloud默认使用的Region是us-east-1,在非AWS环境下,可以将Zone理解成机房,将Region理解为跨机房的Eureka集群。

Eureka包含Eureka Server和Eureka Client两部分,作用如下:

  • Eureka Server提供服务的发现能力,各个微服务启动时会向Eureka注册中心注册自己的信息,如IP、端口服务名称等,Eureka会保存这些信息
  • Eureka Client 实现与Eureka Server的交互,服务启动后,会周期性的向Eureka Server发送心跳续约自己的“租期”,默认间隔时30s
  • Eureka Server在一定时间间隔内如果没有接收到某个微服务实例的心跳,则会注销该实例,这个默认时间间隔时90s
  • Eureka Server同时也是Eureka Client,相互之间注册可实现注册中心的高可用,同时多个Eureka之间通过复制的方式实现注册表中的数据同步
  • Eureka Client 会缓存注册表中的信息到本地,因此无需每次都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server的所有节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用

编写Eureka Server

pom依赖

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

编写启动类

需要在启动类上添加@EnableEurekaServer注解,声明这是一个Eureka Server

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

配置文件

spring.application.name=eureka-server
server.port=8761

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://local:8761/eureka/

配置文件简单说明:

参数名说明默认值
eureka.client.register-with-eureka是否注册到Eurekatrue
eureka.client.fetch-registry是否注册到Eurekatrue
eureka.client.serviceUrl.defaultZone与Eureka Server交互的地址,多个地址间使用英文逗号分隔

由于这里只是一个单机的Eureka Server,因此不存在将自己作为Eureka Client注册到其它Eureka Server,也不存在从Eureka Server获取注册列表,同步其它Eureka Server节点数据的情况,所以这里配置eureka.client.register-with-eureka和eureka.client.fetch-registry都为false,如果是生产环境Eureka Server肯定是高可用的,使用默认配置即可

编写Eureka Client

pom依赖

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

编写启动类

在Spring Cloud Edgware版本之前,需要在启动类上添加@EnableEurekaClient或EnableDiscoveryClient注解,在Edgware之后,只需在pom中添加相关依赖,即可自动注册。

@SpringBootApplication
@EnableEurekaClient
public class UserApplication {

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

}

配置文件

spring.application.name=user-service
server.port=8081

eureka.client.serviceUrl.defaultZone=http://local:8761/eureka/

eureka.instance.prefer-ip-address=true

配置说明:

参数名说明默认值
spring.application.name注册到Eureka Server上的应用的名称
eureka.instance.prefer-ip-address表示将自己的IP注册到Eureka Server而不是hostnamefalse
eureka.client.serviceUrl.defaultZone与Eureka Server交互的地址,多个地址间使用英文逗号分隔

Eureka Server的高可用实现

前文的Eureka Server示例,是一个单节点的注册中心,并不适合线上生产环境。因为当Eureka Server宕机时,Eureka Client不能及时更新缓存中的服务列表,当其中的某个微服务实例出现不可用的情况时,就可能影响整个应用系统的稳定性

Eureka Server改造

只需要改造配置文件即可:

spring.application.name=eureka-server
server.port=9120

eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90
eureka.client.registry-fetch-interval-seconds=30

eureka.client.serviceUrl.defaultZone=http://slave01:9120/eureka/,http://slave02:9120/eureka/

Eureka Client改造

只需要改造配置文件即可:

spring.application.name=user-service
server.port=8081

eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90
eureka.client.registry-fetch-interval-seconds=30

eureka.client.serviceUrl.defaultZone=http://slave01:9120/eureka/,http://slave02:9120/eureka/

配置项说明

参数名说明默认值
eureka.instance.lease-renewal-interval-in-secondsEureka Client发送心跳到Eureka Server的时间间隔30s
eureka.instance.lease-expiration-duration-in-secondsEureka Server接收到最后一个心跳信号后到移除某个实例的等待时间90s
eureka.client.registry-fetch-interval-secondsEureka Client 从Eureka Server上拉取注册信息的时间间隔30s

用户认证

之前的示例中,Eureka Server是允许匿名访问的,实际生产项目中,为了提高安全性,我们只允许经过认证校验的实例注册到Eureka

Eureka Server添加用户认证

pom文件改造:增加spring-security做安全校验

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

application配置文件新增开启认证、用户名和密码配置,并更改Eureka Server连接路径:

security.basic.enabled=true
security.user.name=admin
security.user.password=admin

eureka.client.serviceUrl.defaultZone=http://admin:admin@slave01:9120/eureka/,http://admin:admin@slave02:9120/eureka/

Eureka Client 更改 Eureka Server连接方式

只需要更改application中的连接方式即可:

eureka.client.serviceUrl.defaultZone=http://admin:admin@slave01:9120/eureka/,http://admin:admin@slave02:9120/eureka/

Eureka 元数据

Eureka包含两种元数据:

  • 标准元数据:制定是主机名、IP地址、端口号、状态页和健康检查等信息,这些信息在服务的注册表中,用于服务之间的调用
  • 自定义元数据:使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,如A服务定义了eureka.instance.metadata-map的属性,B服务则可以拿到这个自定义属性。

Eureka Rest端点

常用Rest端点整理:

接口路径功能说明
POST/eureka/apps/appID注册服务输入JSON/XML格式的数据;204:成功
DELETE/eureka/apps/appID/instanceID注销服务200:成功
PUT/eureka/apps/appID/instanceID发送心跳200:成功、404:instanceID对应的服务不存在
GET/eureka/apps查询所有实例200:成功;返回JSON/XML
GET/eureka/apps/appID查询appID对应的所有实例200:成功;返回JSON/XML
GET/eureka/apps/appID/instanceID查询appID下instanceID对应的实例200:成功;返回JSON/XML
GET/eureka/apps/instances/instanceID查询指定的实例200:成功;返回JSON/XML
PUT/eureka/apps/appID/instanceID/metadata?key=value更新指定实例的元信息200:成功、500:失败

Eureka的通信机制使用HTTP的REST接口实现,由于HTTP的平台无关性,虽然Eureka Server通过Java实现,但是其下的微服务应用不限于使用JAVA来开发。

目前已有很多其它语言平台支持Eureka,如eureka-js-client、python-eureka等,如果使用的语言网络上面没有封装好的客户端,我们还可以自己实现,通过使用过Eureka的REST端点,我们可以实现注册服务、注销服务、心跳、服务发现等

Eureka官网REST API 文档:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations

Eureka自我保护模式

当我们在本地单机调试时,经常会在Eureka的首页爆出一个警告,这个警告其实就是Eureka的自我保护机制报出来的。

默认情况下,Eureka Server在一定时间内没有接收到某个微服务的心跳,Eureka Server将注销这个实例(默认90s)。但是当网络发生故障时,Eureka Server和微服务之间无法正常通信,上边的注销行为将非常危险,因为微服务本身其实都时健康的,这个时候不应该注销。Eureka通过“自我保护”的模式解决这个问题,当Eureka Server在短时间内丢失过多的客户端时,就会进入“自我保护”的模式,将这些客户端的实例保护起来,在保护期间,如果实例出现问题,那么调用者很可能拿到实际已经不存在的服务实例,从而造成调用失败的情况出现,所以客户端必须要有容错机制,如请求重试、断路器等机制

本地调试时很容易触发注册中心的保护机制,使得注册中心维护的实例不那么准确。所以,本地开发时,可以用eureka.server.enable-self-preservation=false参数关闭保护机制,以确保注册中心将不可用的实例正确剔除。

参考文档及书籍

官方文档
Eureka Server:https://cloud.spring.io/spring-cloud-static/Edgware.SR5/single/spring-cloud.html#spring-cloud-eureka-server
Eureka Client: https://cloud.spring.io/spring-cloud-static/Edgware.SR5/single/spring-cloud.html#_service_discovery_eureka_clients

参考书籍
Spring Cloud微服务实战
Spring Cloud与Docker 微服务架构实战

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值