凡事皆有代价,一切皆是取舍。
–> 返回Netflix OSS套件专栏汇总 <–
代码下载地址:https://github.com/f641385712/netflix-learning
目录
前言
各位小伙伴大家好,我是A哥。从本系列开始,我们将一起进入Netflix Eureka的学习。本系列文章学习源生Eureka,以及它在Spring Cloud
技术体系中的应用和原理剖析。本文开始研究Spring Cloud体系中的注册中心:当前最流行的Eureka
。Eureka
作为服务注册中心对整个微服务架构起着最核心的整合作用,因此我个人认为对Eureka还是有很大的必要进行深入研究。
说明:Eureka即使你可能很少关注,但不代表架构师不关注它~
正文
服务注册/发现在分布式、微服务架构中有多重要,相信用任何词来形容都不过分,总之它是该架构下的一种必须。下面针对于服务发现的一些基本概念进行科普
“服务发现”和“注册中心”可认为是一组同义词,下面讲解并不区分
何为服务发现(service discovery)?
在微服务架构中,服务之间的调用都需要知道目标地址(ip+port)才能完成访问,这个时候服务发现就可做一些事情:维护一个地址列表(可持久化or基于内存)存储,作为所有地址的中央存储库。
微服务为何需要服务发现?
服务发现对微服务、分布式应用、云源生应用均至关重要,总结起来有如下两大原因:
- 注册中心为应用程序提供了快速扩展的能力,以及缩减在一个环境中运行的服务实例数量(简单说:就是极大的提高了弹性,很方便的进行扩、缩容)
- 可以让provider的地址从client中抽象出来,成为一个逻辑名称。如:client只需知道调用account服务,至于account服务对应的地址具体是哪个并不关心(交由注册中心去管理)。
- provider的物理地址对client端完全透明,进而就可非常方面的实现横向扩展、动态扩、缩容
- 服务发现使整体应用更有弹性。简单的说就是能动态摘除掉“糟糕的实例”,路由到健康的实例,这些对调用者来说完全透明不影响
服务发现机制如何实现?
首先已经达成共识:服务发现是微服务架构的必须。那么如何实现呢?大致的实现方法也是有两种:
基于DNS域名解析的服务发现
这是一种较为古老的交互方式,大致的交互逻辑如下图:
client端在调用其它服务时,通过DNS将域名解析得到一个物理地址,然后把请求转发给该地址。该地址自己内部维护了一张路由表,然后由它来决定最终将请求转发到哪台实际物理实例上去。
该模型大家应该也不陌生,就是典型的域名 + Nginx
负载均衡模型。此种方式有些天然的劣势,举例如下:
- 单点问题。ng是个单点,如果它一旦挂掉,将会影响所有的依赖服务。虽然可以热备一个ng,但是同一时间永远是单点在工作,而单点就一定有能力上限
- 无法水平扩展。因为同一时间工作的只能有一台ng,所以无法做到水平扩展
- 无法动态托管。比如ng背后托管着一批的机器,它无法做到动态嗅探到实例的增、减
- 加长了链路。因为ng只是一个代理,而最终还需要转发到物理机器里去,所以增加了一层DNS转换以及增加了一层转发,使得链路更长了一些
以上4点是这种传统方式的缺点,简单的说就是服务端负载均衡能很好的作用于集中式网络架构(比如大型单体应用)中。但它的扩展能力若弱,扩展效益低使得它不适合微服务架构体系。下面介绍另外一种实现方案
基于注册中心的服务发现
能应用于微服务体系的服务发现应该具备如下特征:
- 高可用:节点信息(ip+port等)能在多个节点间共享。当集群中的某个节点不可用,其它节点可以完全接管。
- 所有节点对等:也就是每个节点必须无状态。
- 客户端负载均衡:略
- 高弹性:托管的节点可以动态扩容、缩容
- 容错/自动故障转移:某个节点出现故障,可以自动T除它然后把流量分到其它实例上
这种方式就是当下我们使用的方式,也是本系列要讲解的内容。
核心概念
基于注册中心实现的服务发现,需要知道如下几个概念,或者说是问题。
- 服务注册:每个节点都需要主动把自己注册到中心里去。(用何种方式???http、tcp?)
- 说明:eureka它并不限制你用什么协议去通信,只不过它内置支持的是基于Rest的,你可以更改成RPC等
- 健康检查监控:若某个实例节点自己不可用了,注册中心如何知晓然后T除它呢?(新增了一个节点简单,它会主动注册上去嘛)
- 客户端获取provider服务地址们:每个节点要调用其它服务需要知道其具体的ip地址。如何获取???
- 注册中心集群节点间信息共享:注册中心有多个节点,多个节点之间数据如何sync?
Netflix Eureka
的服务发现引擎可以实现服务发现,而客户端负载均衡的实现则使用Netflix
的Ribbon
库。
什么是Eureka
eureka
中文释义:我发现了,我找到了。属于感叹词~
官网解释:Eureka是一种基于REST的服务,主要用于AWS云中定位服务,以实现负载平衡和故障转移的中间件。
官网地址:https://github.com/Netflix/eureka
人话:服务发现/注册中心。分为Client端和Server端,是一种中心化(Server端就是注册中心)架构设计。
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-client</artifactId>
<version>1.9.13</version>
</dependency>
说明:和其它库不一样的是,eureka-client
是最为核心、最为底层的一个包,反倒eureka-core
是依赖eureka-client
的。
另外需要特别强调的是:并不存在eureka-server
这个包,哪怕是Server端也仅有eureka-client
和eureka-core
即可,所以你可以简单粗暴的理解为eureka-core
就是服务端必备,它提供了REST接口供以访问的资源们如:VIPResource/InstanceResource/ApplicationResource...
spring-cloud-netflix-eureka-server
这个jar它也仅包含了eureka相关的eureka-client
和eureka-core
这两个包。而对于spring-cloud-netflix-eureka-client
端,你完全可以自己手动排除掉eureka-core
的依赖(只是Spring Cloud没帮你排除,没做得这么细致)。
另外从截图中可以看出,eureka-client
它依赖于jersey发送的Rest请求,关于JSR311(jersey)可参考文章:JavaEE的RESTful标准技术JAX-RS,jersey-client客户端使用介绍【享学Java】
版本约定
遵照同其它Netflix技术一样,采用相同的版本约定。
Spring Boot
版本:2.2.2.RELEASE
Spring Cloud
版本:Hoxton.SR1
,它依赖和对应的版本号如下- Spring Boot版本:2.2.2.RELEASE
- spring-cloud-starter-xxx版本:2.2.1.RELEASE
- eureka版本:1.9.13
Eureka
:1.9.13。它依赖的相关组件版本号如下- jersey:1.19.1(几乎是1.x版本的final版本)
官网要求,Eureka必须构建在JDK8及以上版本。
模块介绍
eureka所有模块截图如下:
Eureka的模块设计有点不一样,
eureka-client
才是它最为底层的包,而非eureka-core。
eureka-client
:微服务通过该客户端与Eureka进行通信,屏蔽了通信的细节eureka-client-archaius2
:基于archaius2.x
实现的配置管理模块(默认是基于1.x)eureka-client-jersey2
:基于jersey2.x
实现rest请求(默认是1.x)eureka-core
:核心模块,依赖于eureka-client
eureka-core-jersey2
:略- …
eureka-server
:eureka服务端代码。依赖于jersey-server1.x来搭建的Servlet应用,并且它还依赖于eureka-client
的- 包含了servlet应用的基本配置,如
web.xml
。构建成功后在该模块下会生成可部署的war包。
- 包含了servlet应用的基本配置,如
Tips:有个奇怪的现象是客户端和服务端均不直接依赖
eureka-core
。但是,但是,但是spring-cloud-starter-netflix-eureka-server
依赖了eureka-core
eureka-core模块简介
该工程的core模块显得很不一样,它不是所有的基础,而是仅仅用于Server端,并且还不是必须的。
对其每个包的功能做基础解释:
com.netflix.eureka.aws
:与amazon AWS服务相关的类(我们一般用不着)com.netflix.eureka.cluster
:与peer节点复制(replication)相关的功能,节点数据共享com.netflix.eureka.lease
:即”租约”, 用来控制节点注册的生命周期(添加、清除、续约)com.netflix.eureka.registry
:存储、查询服务注册信息com.netflix.eureka.resources
:RESTful风格中的”R”, 即资源。相当于Spring MVC
中的Controllercom.netflix.eureka.transport
:发送HTTP请求的客户端,如发送心跳(因为节点间赋复制需要它)
Eureka Client端动作
Eureka Client是一个Java客户端,用于简化与Eureka Server的交互,屏蔽内部通信细节。Eureka Client会拉取、更新和缓存Eureka Server中的信息(注意:这个拉取动作并不是启动时完成的)。即使所有的Eureka Server节点都宕掉,短时间内服务消费者依然可以使用缓存中的信息找到服务提供者。
Eureka Client在微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒)。
Client端机制是30s续租一次,Server端机制是90秒木有收到就认为你挂了。这是不同端的两种机制
它具有如下动作:
- 服务注册Register:client端主动向Server端注册。提供自身的元数据,比如IP地址、端口,运行状况指示符URL,主页…等
- 服务续约Renew:Client默认会每隔30秒发送一次心跳来续约。这样来告诉Server说我还活着
- 续约机制中,Server端默认在90秒没有收到Eureka客户的续约的话,就会将该实例从Server端T掉
- 获取注册列表信息Fetch Registries:Client端从Server获取注册表信息,并将其缓存在本地。缓存信息默认每
30s
更新一次(每次返回的和缓存的可能形同也可能不同,Client端自行处理从而发送不同的事件)- 默认的情况下Client端使用压缩JSON格式来获取注册列表的信息(还支持xml格式)
- 服务下线Cancel:Client端在停机时(注意是正常停止)主动向Server端会发送取消请求,告诉Server端把自己这个实例T掉
客户端T除的是provider实例信息(但Server端可能还有),服务端T除的是client端实例信息(但Client端可能还有)
Eureka Server端动作
提供给各个微服务注册的服务器(单独部署,集群部署),Eureka Server会存储该服务的信息(放在内存)。
Server端并不会主动触发动作,主要用于提供服务:
- 提供服务注册:
- 提供服务信息拉取(查询):
- 提供服务管理:接口客户端的cancle、心跳、续租renew等请求
- 服务剔除Eviction:在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,Eureka服务器会将该服务实例从服务注册列表删除,即服务剔除。
- 信息同步:在集群中,每个Eureka Server同时也是Eureka Client。多个Server之间通过P2P复制的方式完成服务注册表的同步。
- 同步规则:若有3个Eureka Server,Server1有新的服务信息时,同步到Server2后,Server2和Server3同步时,Server2不会把从Server1那里同步到的信息同步给Server3,只能由Server1自己同步给Server3
每个可用区有一个Eureka集群,并且每个可用区至少有一个eureka服务器来处理区内故障。为了实现高可用,一般一个可用区中由三个Eureka Server组成。
Eureka Client同Server的通讯方式
默认情况下,Eureka Client使用Jersey和Jackson以及JSON有效负载与Eureka Server进行通信。您可以通过覆盖默认机制来使用您选择的机制。请注意,对于某些遗留用例(比较老的项目),XStream
也是依赖关系图的一部分。
Eureka和Eureka与AWS ELB有何不同?
AWS Elastic Load Balancer
是针对暴露于最终用户Web流量的边缘服务的负载均衡解决方案,也就是面向公网的。而Eureka满足了中层负载均衡的需求。
AWS ELB还是传统的基于代理的负载均衡解决方案;eureka的负载均衡发生在实例/服务器/主机级别,Client端知道它们需要与哪些服务器通信的所有信息,这是优点还是缺陷就看你如何理解它喽。
在Netflix公司内,我们希望我们的服务是无状态的(非粘性)。这有助于建立更好的可伸缩性模型,而Eureka非常适合解决此问题。对于非Java客户端想使用Eureka怎么办?其实是可以的,Server端通用,不过客户端需要你提供对应的语言版本,或者使用side car
。
关于Eureka Server服务端的搭建说明
因为Eureka分为Client端和Server服务端,本系列会对每个端都进行单独讲解。但在讲解Client端的时候,要辅以示例代码,所以肯定是需要单独启动一个Eureka Server
线程,Server端打包完后就是一个单独的war包,可以部署到tomcat里运行。
但是,Eureka
的源码是基于gradle
构建的,并且使用的gradle
版本还比较老,构建起来比较费劲(不瞒你说,很多坑)。另外,本人对gradle了解也并不多,因此:为了避免不必要的麻烦,并且能更好的看到效果(有页面),本文示例中Eureka Server
服务端使用Spring Cloud快速完成构建~
也就是使用
spring-cloud-starter-netflix-eureka-server
该工程来实现服务端的搭建
主流注册中心对比
当下流行的有好几种注册中心,当然本文不做详细对比,只提供一张对比图有个初步映象就成:
我个人认为:对于注册中心推荐选的只有Eureka
和阿里的Nacos
。因为注册中心作为微服务架构的核心中间件,因此对可用性是强要求,反倒对一致性是可以容忍的,基于此 AP模式的只有Eureka
和Nacos
。
当然,纯属个人意见,各位自取
总结
关于源生Eureka介绍 — 基于注册中心的服务发现就先介绍到这。本文内容是对注册中心、Eureka的一个概述,对一些核心概念进行了普及,接下来便会深入到应用、源码层面进行一层层剖析。
关注A哥
Author | A哥(YourBatman) |
---|---|
个人站点 | www.yourbatman.cn |
yourbatman@qq.com | |
微 信 | fsx641385712 |
活跃平台 | |
公众号 | BAT的乌托邦(ID:BAT-utopia) |
知识星球 | BAT的乌托邦 |
每日文章推荐 | 每日文章推荐 |
- [享学Jackson] 一、初识Jackson – 世界上最好的JSON库
- [享学Jackson] 二、jackson-core之流式API与JsonFactory、JsonGenerator、JsonParser
- [享学Jackson] 三、jackson-databind之ObjectMapper与数据绑定、树模型
- [享学Jackson] 四、控制Jackson行为的特征们之JsonFactory.Feature、JsonGenerator.Feature、JsonParser.Feature
- [享学Jackson] 五、控制Jackson行为的特征们之JsonWriteFeature、JsonReadFeature
- [享学Jackson] 六、控制Jackson行为的特征们之MapperFeature、SerializationFeature、DeserializationFeature
- [享学Jackson] 七、Jackson使用bit位运算来开启/禁用Feature的原理解析
- [享学Jackson] 八、jackson-databind数据绑定基础配置之BaseSettings、MapperConfig、MapperConfigBase
- [享学Jackson] 九、jackson-databind数据绑定序列化/反序列化配置之SerializationConfig、DeserializationConfig
- [享学Jackson] 十、jackson-databind序列化之ObjectMapper序列化原理、序列化器匹配原理
- [享学Jackson] 十一、jackson-databind之JsonSerializer序列化器全解析
- [享学Jackson] 十二、jackson-databind反序列化之ObjectMapper反序列化原理、JsonDeserializer反序列化器全解析
- [享学Jackson] 十三、jackson-annotation注解模块全解析及Jackson注解大全
- [享学Jackson] 十四、深入理解Jackson的Module模块化设计及原理分析
- [享学Jackson] 十五、第三方模块Module的深度实践:JavaTimeModule、JSR310Module、ParameterNamesModule、Jdk8Module
- [享学Jackson] 十六、Jackson在Spring MVC中的使用之Date、JSR310时间类型的处理
- [享学Jackson] 十七、spring-web整合Jackson源码解析之Jackson2ObjectMapperBuilder
- [享学Jackson] 十八、Spring容器深度整合Jackson的桥梁之SpringHandlerInstantiator
- [享学Jackson] 十九、Spring下使用ObjectMapper的正确姿势 — Jackson2ObjectMapperFactoryBean
- [享学Jackson] 二十、Spring MVC下的Jackson — MappingJackson2HttpMessageConverter
- [享学Jackson] 二十一、Spring Boot下的Jackson — JacksonAutoConfiguration自动配置
- [享学Jackson] 二十二、Jackson与Fastjson的恩怨情仇(完结篇)