Spring cloud 的注册中心

 
  • 服务发现
  • spring-cloud-eureka

服务发现

服务发现技术选型

Jason Wilder 在 2014 年2 月的时候写了一片博客 Open-Source Service Discovery, 总结了当时市面上的几类服务发现组建.

名称 类型 AP/CP 语言 依赖 集成 一致性算法
Zookeeper General CP java JVM Client binding Paxos
Doozer General CP Go   Client Binding Paxos
Consul General CP Go   HTTP/DNS Library Raft
Etcd General CP or Mixed(1) Go   Client Binding /HTTP Raft
SmartStack Dedicated AP Ruby haproxy/Zookeeper Sidekick (nerve/synapse)  
Eureka Dedicated AP Java JVM Java client  
NSQ (lookupd) Dedicated AP Go   Client Bindign  
Serf Dedicated AP Go   Local CLI  
Spoify(dns) Dedicated AP N/A Bind DNS Lisbrary  
skyDNS Dedicated Mixed(2) Go   HTTP/DNS library  
Nacos General AP + CP Java JVM Java client  

从上面的表中可以看到, 服务发现有很多组建可以选择.

spring-cloud-eureka

Netflix Eureka 是 Netflix 开源的一款基于 REST 的服务发现组建, 包括 Eureka Server 和 Eureka Client. Sring Cloud Netflix Eureka 是 Pivotal 公司为了将 Netflix Eureka 整合于 Spring Cloud 生态中提高的版本, 目前 spring cloud 中使用的 Eureka 是 1.x 版本.

Eureka 提供的服务发现可以为负载均衡, failover 等提供支持.

Eureka 最初是针对 AWS 不提供中间服务层的负载均衡的限制而涉及开发的. AWS Elastic Load Balancer 用来对客户端或终端设备进行负载均衡, 而 Eureka 则用来对中间层的服务做服务妨碍安, 配合其他组建提供负载均衡的能力.

设计 Eureka 主要是因为, 如果直接使用 AWS 的 ELB 对内部进行负载均衡, 会将内部应用暴露到外网, 存在安全性问题; 还有就是 AWS 的 ELB 是传统的基于代理的负载均衡解决方案, 无法直接就服务元数据信息定制负载均衡算法, 设计的 Eureka 一方面给内部服务做服务发现, 另一方面可以结合 ribbon 组建提供各种个性化的负载均衡算法.

而 AWS Route 53 是一款命名服务, 可以给中间层的服务提供服务妨碍那功能, 但是他是基于 DNS 的服务, 传统的基于 DNS 的负载均衡技术存在更新掩饰问题, 另外主要是无法对服务健康状态进行检查.

Eureka 和 Consul 的区别

Eureka Server 段采用的是 P2P 的复制模式, 但是它不保证复制操作一定鞥成功, 因此它提供的是一个最终一致性的服务实例试图; Client 端在 Server 端的组册信息有一个带期限的租约, 一旦 Server 端在指定期间没有收到 Client 端发送的心跳, 则 Server 端会认为 Client 端注册的服务是不健康的, 定时任务会将其哦难过注册表中删除.

Consul 采用 Raft 算法, 可以体统强一致性的保证, Consul 的 agent 相当于 Netflix Ribbon + Netflix Eureka Client , 而且对应用来说相对透明,同时相对与 Eureka 这种集中式的心跳检测机制, Consul 的 agent 可以篡预到基于 gossip 协议的健康检查, 分散了 Server 端的心跳检测压力. 此外, Consul 为多数据中心提供了开箱即用的原生支持等.

那么居于什么考虑因素可以选择 Eureka 呢? 主要原因有如下几点:

  • 选择 AP 而不是 CP
  • 团队都是使用 Java 语言开发的.(技术上比较统一, 出现问题也好排查修复, 对组建的掌控力比较强, 防办扩展维护)
  • Eureka 是 Netflix 开源套件的一部分, 和 zuul / ribbon 等整合比较好.

Eureka 的设计理念

作为一个服务注册及发现中心,主要要解决以下几个问题:

  • 服务实例如何组册到服务中心

    本质上就是在服务启动的时候,调用 Eureka 的 REST API 的 register 方法。

  • 服务实例如何从服务中心中剔除

    正常情况下服务实例在关闭应用时,应该通过 hook 方法或者其他生命周期回调方法取调用 Eureka Server 的 rest ap 的 de-register 方法,来删除自身服务实例的信息, Eureka server 要求 client 定时进行续约, 就是发送心跳,来证明该服务实例是存活的、健康的、可以调用的。如果超时没有进行续约,Eureka Server 会主动剔除。

一致性问题

AP 优于 CP

分布式系统中有个重要的 CAP 理论,该理论由加州大学伯克利分校的 Eric Brewer 教授提出,由麻省理工学院的 Seth Gilbert 和 Lynch 进行理论证明。该理论提到了分布式的三个特性:

  • Consistency: 数据一致性,即数据在存在多个副本的情况下,可能由于网络、机器故障、软件系统等问题导致数据写入部分副本成功,写入部分副本失败,进而造成副本之间数据不一致,存在冲突。满足一致性则要求对数据的更新操作成功之后,多个副本的数据保持一致。
  • Availabiity: 可用性,在任何时候客户端对集群进行读写操作时,请求能够得到正常的响应。
  • Partition Tolerance:分区容忍性,即发生通信故障的时候,郑哥集群被分割为多个无法互相通信的分区时,集群仍然可用。

对于分布式系统来说,一般网络条件不可控,出现网络分区时不可避免的,因此系统必须具备分区容忍性。在这个前提下分布式系统的设计则在 AP 和 CP 之间进行选择。不过不能理解为CAP 三者之间必须三选二,他们三者之间不是对等的可以互相替换的。在分布式系统领域,P 时一个客观存在的事实,不可绕过,所以 P 与 AC 之间不是对等关系。

对于 Zookeeper ,它时属于 “C”P 的,之所以给 C 加上引号,是因为 Zookeeper 默认并不是严格的请一致性,比如客户端 A 提交一个写操作,ZooKeeper 在过半数节点操作成功之后就返回,此时假设客户端 B 的读操作请求到的是 A 写操作尚未同步到的节点,那么读取到的就不是客户端 A 写操作成功之后的数据。如果在使用的时候需要强一致,则需要在读取数据的时候先执行一下 sync 操作,即与 leader 节点先同步下数据,这样才能保证强一致。在极端的情况下发生网络分区的时候,如果 leader节 点不在 nonquorum 分区,那么对这个分区上节点的读写请求将会报错,无法满足 Availability 特性。

Eureka 是在部署在 AWS 的背景下设计的,其设计者认为,在云端,特别是在大规模部署的情况下,失败是不可避免的,因此不能回避这个问题。要拥抱这个问题,就需要 Eureka 在网络分区的时候,还能够正常提供服务注册及发现功能,因此Eureka选择满足Availability这个特性。PeterKelley在 Eureka!WhyYouShouldn’tUseZooKeeperforServiceDiscovery 一文中指出,在实际生产实践中,服务注册及发现中心保留可用及过期的数据总比丢失掉可用的数据好。这样的话,应用实例的注册信息在集群的所有节点间并不是强一致的,这就需要客户端能够支持负载均衡及失败重试。在Netflix的生态中,由ribbon提供这个功能。

Nacos

Nacos 和 Eureka 都是注册中心,都具有各自的负载均衡策略,Eureka 分为Eureka Server(Eureka服务)和 Eureka Client(Eureka客户端),所有 Eureka Server 通过 Replicate 进行数据同步。无论 Eureka Client 向哪个 Eureka Server 中注册信息,最终所有 Eureka Server 中都会存储注册的信息,这些信息都缓存到 Eureka Server 的本地。

Eureka Client 在启动后,每隔 30 秒向 Eureka Server 发送一次心跳,以证明自己的可用。当 Eureka Server 超过 90 秒没有收到提供者的心跳后,会认为这个 Client 已经宕机,进而销毁实例。

Nacos 有自己的配置中心,Eureka 需要配合 config 实现配置中心,且不提供管理界面,Nacos 是动态刷新的,它采用 Netty 保持长连接实时推送,Eureka 需要配合 MQ 实现配置动态刷新。

阿里的 Nacos : 性能最好,他同时支持 AP 和 CP 模式,他根据服务注册选择临时和永久来决定走 AP 模式还是 CP 模式。

Eureka : 可以做注册中心,完全AP,支持注册中心之间的节点复制,同时支持服务端同时注册多个注册中心节点,所以不存节点信息不一致的情况。?

连接方式:

Nacos 使用 Netty 是长连接

Eureka 使用 RESTful api 是短连接,定时发送心跳。

并发量:

Nacos 支持较高的并发量

Spring Cloud Consul

Consul 是一个分布式的高可用的服务网格(service mesh)解决方案,提供了包括服务发现、配置和分段功能在内的全功能控制平面。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务网格。

Consul 是什么

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框架、分布式一致性协议实现、健康检查、Key/Value 存储(配置中心)、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等),使用起来也较为简单。

Consul 使用 Go 语言编写,因此具有天然可移植性(支持 Linux、Windows 和 Mac OS);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。

  • Consul 使用 Go 语言编写,以 Http 方式对外提供服务。
  • Consul 支持多数据中心。
  • Consul 服务发现。
  • consul 的一致性协议是 Raft。
  • 支持 http 和 dns 协议接口
  • 提供 Web 管理界面

Consul 能做什么

  • 服务发现
  • 健康检查
  • K/V 存储
  • 多数据中心。

安装

1, 下载:

https://www.consul.io/downloads

2, 启动:

consul agent -dev -ui -client=0.0.0.0

安全与权限

我们发送请求通过负载均衡软件,负载均衡发到微服务网关上,网关进行用户的认证,解析出用户的基本信息,通过认证后,携带用户本身的标识到后台微服务,微服务获得标识后进行相关的鉴权,这样就能形成一个完整的权限链路。

我们首先来简单解释下,认证和鉴权这2个名称的含义,

  • 认证:通俗来讲,就是要验证这个用户是谁。
  • 鉴权:通俗来讲,就是要了解这个用户能做什么事。

微服务下 SSO 单点登录方案

传统的做法就是通过 SSO 来实现,但在微服务架构中,单体应用按照规则拆分成很多小的服务,这种情况下,如果对每个服务都进行每个用户的 SSO 动作,那么每个服务里都会做用户的认证和鉴权,可能保存用户信息或者每个用户都会和鉴权服务打交道,这些情况都将会带来非常大的网络消耗和性能损耗,也有可能会造成数据不一致,所以不太建议用这种方案。

分布式 Session 与网关结合方案

步骤:

1, 用户在网关进行 SSO 登录,进行用户认证、检查用户是否存在和有效。

2, 如果认证通过,则将用户信息或者数据存储在第三方共享存储中,(MySQL,Redis)。

3, 后端微服务可以从共享存储中拿到用户的数据。

很多场景下,这种方案是推荐的,因为方便,并且易于扩展。缺点是依赖于第三方组件,并且这些组件需要做到高可用以及安全的控制。

客户端 Token 与网关结合方案

步骤:

1, 客户端持有一个 Token,通常可以用 JWT 或者其他加密的算法实现自己的一种 Token,然后通过 Token 保存了用户的信息。

2, 发起请求并携带 Token, Token 传到网关后,网关层进行认证和校验。

3, 如果通过校验,携带 Token 到后台的微服务中,可以进行具体的借口或者 url 验证。

4, 如果要涉及用户的大量数据存放,则 Token 就有可能不太合适,或者结合上面的分布式 Session , 使用第三方存储来储存这些信息。

这种方案也是业界很常用的方案,但是对于 Token 来说,它的注销会有一定的麻烦,需要在网关层进行 Token 的注销。

就是把用户信息放在 Cookie 里。

网关与 Token 和服务间鉴权结合

1) 在Gateway网关层做认证,通过对用户校验后,传递用户的信息到header中,后台微服务在收到header后进行解析,解析完后查看是否有调用此服务或者某个url的权限,然后完成鉴权。

2) 从服务内部发出的请求,在出去时进行拦截,把用户信息保存在header里,然后传出去,被调用方获取到header后进行解析和鉴权。

EOF