eurela client存在于每个provider和consumer中。
eureka client有以下动作:
如果在代码中,一个服务调用了另一个服务的接口,那么当前服务会从本地的注册表缓存中根据要调用的服务的serviceID获取到服务信息,根据服务信息通过http(Spring Cloud Feign,Spring boot2.X使用的是openfeign,在从1.X升级到2.X时注意feign包的引用)请求去调用。
eureka service是服务注册中心,可以存在多个,因此可以部署eureka service的集群保证高可用。如果当一个节点挂掉,比如,此时有个服务发起renew请求,发现连接失败。eureka会自动切换到另一个节点;除非eureka service全部挂掉,那神仙也没办法。
当15分钟内,集群中超过85%的客户端,没有正常心跳,则会开启自我保护机制。此时eureka server不再剔除注册表中的客户端,当此时eureka server接收到客户端注册请求,会在当前节点上注册,但是不会同步到其他eureka server节点上。当网络恢复正常,也就是集群中的节点恢复正常心跳后。则会把注册信息同步到其他的eureka server节点。
eureka service有以下动作:
通过eureka记录了服务信息后,还并不能调用远程服务。因为eureka只提供服务的注册与发现,不提供远程调用。
Eureka更新到2.0版本后,官方已经停止维护。
consul与eureka的区别:
consul提供CP(一致性、分区容错性)的保证,consul使用Raft协议保证其一致性。如果一个普通节点挂了,那么整个系统不会down掉,请求会转移到活着的节点上。但是当集群leader挂了后,集群会停止服务,直到新的leader选出来之后。集群才可继续运转。并且在服务注册时,服务信息需要同步写入集群的半数以上的机器才算成功,服务注册速度相对于eureka更慢,这就是为什么能保证CP缺不能保证A(可用性)的原因。
eureka提供了AP(可用性、分区容错性)的保证,eureka通过弱一致性,保证了集群的AP(可用性、分区容错性),当eureka的一个普通节点挂掉以后,请求也是会往另外的节点转发过去,当eureka service集群的某个节点挂掉后,服务也可以照常运行。因为eureka service通常由3台或更多的服务器组成eureka service,eureka service的数据会互相同步。但是在同步时,不会保证每次数据同步都能完成。并且eureka的服务注册相对于consul更快,因为eureka的服务只需要在集群中的一台eureka service上注册成功就算服务注册完成,之后再去eureka service中同步服务信息,这就导致了可能在eureka service1能成功调用该新注册的服务,但是eureka service2中调用不了该新注册的服务,所以虽然eureka service中的注册信息虽不一致,但集群依然能正常运作。
Spring Cloud Feign是Spring Cloud中的核心组件,如果没有了Feign,那么分布式集群的远程调用将会变的复杂无比。
@EnableFeignClients
是启用feign最基础的注解。注解中使用了@Import(FeignClientsRegistrar.class)
导入了feign组件的注册器,以下是工作原理:
defaultConfiguration
,如果定义了,则生成自定义配置的bean。未定义则使用系统默认的。该配置指定了Decoder
解码器、Encoder
编码器、Contract
组件扫描构造器。basePackages
定义的包地址,如果未定义basePackges
,则扫描全包。@FeignClient
的类。获取到@FeignClient
注解的配置的值,如value/name
、path
等。Ribbon
客户端选择一个主机地址。根据value/name
、path
等值,封装成一个Request,调用目标主机。fallback
信息,如果fallback
未设置,该fallback
指定了用户自定义的失败回调配置类,可以通过配置hystrix
来控制服务的熔断和降级功能。在我们平常使用Spring Cloud服务时,是感受不到Ribbon
的存在的,因为feign封装了Ribbon
,使得调用远程服务的方式变得异常简单,只需要两个注解@EnableFeignClients
和@FeignClient
即可实现远程调用和负载均衡。
Ribbon
默认使用的策略是轮询策略,集群中的每台服务器都可“雨露均沾”
feign把相关参数都包装好后,生成的request最终通过FeignClientFactoryBean.loadBlance
方法调用Ribbon
负载均衡客户端。
Spring Cloud Ribbon
根据feign传过来的参数封装成RibbonRequest
,通过负载均衡算法,在eureka service
提供的服务注册表中选择一台最合适的主机,最终调用到一台目标主机。
在使用feign的时候如果使用注解@EnableFeignClients
时定义了url
参数,那么不会使用负载均衡。反之,则使用的是负载均衡。
Hystrix是为了解决微服务容错性问题,在微服务架构中,底层服务经常有复杂的依赖关系,比如:订单服务依赖积分、库存等服务。如果下单时,积分服务挂了,或者积分服务超时,前面的请求还在处理,后面的请求又过来了。一直卡在积分服务这里,又会导致订单服务超时。就会导致雪崩效应,这时Hystrix提供了快速失败和降级功能。当检测到积分服务超时或报错时,接下来通往积分服务的请求都会快速失效,然后订单服务可以继续执行接下来的流程。
Hystrix主要有以下特点:
在@FeignClient
这个注解中有一个fallback
和fallbackFactory
两个参数,两个参数都定义了当请求失败后,需要执行的类。该类可以自定义的实现一些请求失败后需要进行的操作,该类需要实现FeignClient
接口。
Zuul是整个Spring Cloud项目的入口,前端过来的请求都需要经过Zuul,然后Zuul根据请求找到后台对应的服务。
Zuul的特点:
Zuul虽然在2.X的版本使用了非阻塞的方式实现,但是Netflix官宣Zuul2.X后不再维护开源版本,且Spring Cloud暂时也没有整合的计划。可以考虑换一波Spring Cloud Gateway了。
zuul的filter一共有四个生命周期:
我们可以实现ZuulFilter,然后根据不同的生命周期来做不同的事情。
zuul提供了ZuulFallbackProvider接口,该接口提供了getRoute和fallbackResponse两个方法。getRoute方法主要指定对哪个服务进行熔断,fallbackResponse可以指定熔断后的返回数据。
ZuulFallbackProvider是1.x的版本,2.x里使用FallbackProvider。
对于Zuul来说,Gateway使用Spring5+开发,并且官方宣称性能要比Zuul好。不过这些都不是理由,我觉得还是稳定性。Spring Cloud Gateway目前GitHub的活跃度和社区建设来说要比zuul好得多,因为毕竟open zuul是官方弃子,而且Spring Cloud Gateway是spring的官方项目并且经过生产实践,不用担心稳定性的问题。
Spring Cloud Gateway对比Zuul1.X:
功能 | Gateway | Zuul |
---|---|---|
Websockets | 支持 | 1.X不支持,使用servlet 2.5开发,2.X支持 |
非阻塞 | 支持 | 1.X不支持,2.X支持 |
Spring Cloud Gateway使用Spring 5 + Spring Boot 2开发,所以在项目中使用时。mvn包不能引用mvc的包,直接引用webflux的包即可。
其实对于网关来说,最重要的功能也就几个:路由、请求过滤、转发。所以gateway和zuul的功能性上面其实是几乎一样的。
Spring Cloud请求流程如下:
Spring Cloud Gateway(或Zuul) -> consul(或eureka) -> feign -> ribbon -> hystrix