跳转到内容

1. eureka服务治理

服务发现的由来

从架构部署的角度

单体架构应用的服务自成一体,大多不需要以来其他外部服务,但是有些也需要依赖外部服务,此时使用配置域名的方式,直接访问即可。

到了soa架构时代,服务化的架构内部依赖比较多,主要通过两种方式实现服务发现:

  1. 服务消费者配置服务生产者的upstream。这样的缺点是服务消费者耦合了服务生产者的实现细节,例如,服务生产者需要添加一台主机,那么就需要服务消费者修改配置。
  2. 服务生产者提供统一的内网域名。这样,如果服务生产者需要添加一台主机,只需要在自己的前置机上添加一个ip地址即可。

再往后发展,到了微服务时代,随着docker的流行,底层运维方式发生了巨大变化,业务不在部署在固定的虚拟机上,ip也不会一成不变。这时候,前面的方案就有些捉襟见肘了。但针对这个问题,不同的思考方式提供了不同的解决方案,下面列举几个:

  1. 以ng为例,直接手工或通过脚本方式,在部署的时候直接更新ng的配置文件,然后在reload。或者是使用ngx_http_dyups_module通过rest api在运行时直接更新upstream,而不需要reload。
  2. 直接把服务注册中心作为一个标配的分布式服务组件引入系统,网关组件从服务注册中心获取相关服务的示例信息,从而达到动态路由。

从开发实现的角度

随着架构的发展,单体应用逐步过渡为微服务应用,服务之间的依赖会越来越多。假设团队b、c、d的服务需要团队a的服务提供接口,那么团队a中的服务就需要提供给团队b、c、d一个接口地址,此时如果团队b需要团队a提供一个新的接口地址,那么团队a就需要修改代码,同时团队c或d也需要提供一个新的接口地址,则团队a同样需要修改代码。就会出现这样的情况:就是不管团队b、c、d哪一个消费者需要增加一个接口或修改一个接口甚至弃用一个接口,抑或是团队a的项目需要进行扩容,都需要团队a修改自己的代码,这就造成了核心系统频繁修改代码。这其实是一个强耦合的关系,但是如果引入服务发现组件,团队b、c、d只需要与服务发现组件进行连接,即可获取团队a的代码,这样就可以达到解耦的目的。同时,不论团队a的服务扩容还是缩容,对b、c、d都不会产生过多影响。

总结

服务发现组件出现的主要目的是为了解决服务与服务间过多依赖形成强耦合关系的问题。随着技术不断演进,服务发现组件的功能也在不断增强,服务组册、服务监测、服务路由、负载均衡、自我保护等功能被引进来,也就逐步形成了服务治理组件的全部功能。

SpringCloud Eureka简介

产生

由netflix公司开源,是为了解决aws不提供中间服务层的负载均衡问题而设计开发的。可以提供负载均衡、failover等支持。之所以产生eureka组件,而不使用原有的AWS Elastic Load Balancer,是因为WS Elastic Load Balancer需要暴露地址给外网,这样造成不安全的问题。另外一方面是因为,WS Elastic Load Balancer是基于代理的负载均衡,无法直接基于服务元数据信息定制负载均衡算法。由此就产生了eureka。

技术选型

主要介绍consul与eureka的区别。eureka服务端采用的是p2p的复制模式,不能保证复制操作一定能成功,它提供的是最终一致性的服务实例视图;客户端在服务端的注册信息有一个带期限的租约信息,一旦服务端在指定期限内没有收到客户端的心跳,则服务端就认为客户端组册的服务是不健康的,定时任务就会把客户端组册的服务剔除。consul采用的是raft算法,可以提供强一致性保证,并且consul的agent相当于ribbon和eureka客户端,对应用相对透明,同时相对eureka的集中式心跳检测机制,consul的agent可以参与到基于gossip协议的健康检查,这样分散了服务端的心跳检测压力。此外,eureka是由java编写,consul由go编写;eureka支持ap,consul支持cp。

但是如果团队选择的是ap,不是cp,并且团队是java语言体系,对组件的掌控力较强,则可以使用eureka。此外,eureka还提供了restful风格的api,可以针对注册到eureka上的服务进行操作。

入门案例

  • 创建pom工程,引入SpringCloud、SpringBoot-starter的相关依赖。
  • 创建eureka服务器端工程。
    • 引入依赖
    • 创建主启动类,并在主启动类中添加@EnableEurekaServer注解,以打开服务器端服务注册开关
    • 修改配置文件,设置serviceUrl路径以及其他信息
  • 创建服务生产者工程。
    • 引入依赖
    • 创建主启动类,并在主启动类中添加@EnableDiscoveryClient注解,打开客户端服务注册开关
    • 修改配置文件,设置serviceUrl路径信息与eureka服务器端工程一致
    • 书写业务代码,给服务消费者提供服务
  • 创建服务消费者工程。
    • 引入依赖
    • 创建主启动类,并在主启动类中添加@EnableDiscoveryClient注解,打开客户端服务注册开关
    • 修改配置文件,设置serviceUrl路径信息与eureka服务器端工程一致
    • 书写业务代码,调用服务消费者提供的服务

此过程不全,需要进行完善。需要补充服务消费者调用服务生产者的配置和调用代码。

REST API

  • 查询实例
    • 查询所有应用实例信息
    • 根据appid查询实例信息
    • 根据appid及instanceid查询实例信息
    • 根据instanceid查询实例信息
  • 操作实例
    • 注册新实例
    • 注销实例
    • 暂停、下线实例
    • 恢复实例
    • 发送应用实例心跳数据
    • 修改实例元数据

源码

核心类

  • InstanceInfo:注册的服务实例
  • LeaseInfo:实例的租约信息
  • ServiceInstance:服务的通用信息
  • InstanceStatus:服务实例的状态信息
  • LeaseManager:此接口定义了应用服务实例在服务中心的几个操作方法。
  • LookupService:此接口定义了客户端从服务中心获取服务实例的查询方法
  • InstanceRegistry:
  • AbstractInstanceRegistry
  • PeerAwareInstanceRegistryImpl
  • 。。。

服务的核心操作

  • register
  • cancel
  • renew
  • evict

Eureka的设计理念

  • 服务实例如何注册到服务中心
    • 本质是服务启动时,调用Eureka Server的REST api的register方法,去注册该应用实例的信息。有两种方法,对java应用程序,可以使用Netflix的Eureka Client封装的API调用注册;对于SpringCloud的应用,可以使用spring-cloud-starter-netflix-eureka-client,基于SpringBoot的自动化配置,自动实现服务信息的注册。
  • 服务实例如何从服务中心剔除
    • 正常情况下服务实例在关闭应用时,通过钩子的方法或者生命周期回调方法去调用EurekaServer的RESTApi的de-register方法,来剔除自身服务实例的信息。此外为了解决服务实例挂掉或者其他异常信息导致没有及时剔除自身信息的问题,EurekaServer会要求Client端定时续约,即发送心跳,来证明实例实例是正常的,如果租约超过一定时间没有进行续约操作,Eureakserver就会进行自动删除。

总结

由架构发展演进过程引入服务发现组件,通过Netflix公司开源其自研的服务发现组件eureka来介绍服务发现组件的主要实现技术,由此引入eureka的应用案例,并简单介绍了eureka的其他特性。此外,还添加了eureka和其他同类产品的对比。

make it come true