遇到问题:
在使用Spring Cloud Eureka的时候就已经接触到了ribbon, 在RestTemplate的bean上加@LoadBalanced注解,彦江哥说加了它就实现了负载均衡,非常不理解这是为什么。所以Spring Cloud Ribbon到底是什么作用呢?ribbon和这个注解之间有是什么关系呢?
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。
Spring Cloud Ribbon是一个工具框架,不像服务注册中心那样需要部署,它几乎存在于每个Spring Cloud构建的微服务和基础架构中,因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon完成的。后续要介绍的Feigin,也是基于Ribbon实现的工具。
思考:客户端为什么需要负载均衡?Ribbon又是如何实现客户端的负载均衡的?
(回答:通过下面知道客户端的负载均衡维护的是服务端清单,而不是所谓的客户端清单; 具体实现过程见第。。节)
负载均衡的好处:对系统的高可用、网络压力的缓解、处理能力扩容的重要手段。
我们通常说的负载均衡都是服务端的负载均衡,其中可以分为硬件的负载均衡和软件负载均衡。硬件的负载均衡就是再服务器节点之间安装用于负载均衡的设备,比如F5; 软件负载均衡则是再服务器上安装一些具有负载均衡功能的模块或软件来完成请求分发的工作,比如nginx。服务端的负载均衡会在服务端维护一个服务清单。
客户端负载均衡:所有的客户端都维护着自己要访问的服务端清单(是服务端实例清单)。而这些服务端清单来自服务注册中心。客户端负载均衡也需要心跳检测维护清单服务的健康性,只不过这个工作要和服务注册中心配合完成。
思考:服务端和客户端都有负载均衡,会冲突吗?
通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡非常简单, 两步:
(RestTemplate的使用方式相对简单,就先不整理了, 其使用过程在Eureka整理时的代码部分已经实现了)
思考:这么简单么?RestTemplate和Ribbon的客户端负载均衡有什么关系呢?底层就是做了什么样的工作呢?详细分析见Ribbon的源码分析。
(参考链接 http://cmsblogs.com/?p=12852)
思考:Ribbon既然实现了负载均衡的功能,类比nginx, 那么Ribbon应该包含的功能包括:
两种方式:
1、在配置文件中配置
。。。。
2、和eureka集成
在eureka客户端中初始化一个EurekaRibbonClientConfiguration类,其中的ribbonServerList()方法,就是初始化服务列表的方法。
每一个ribbon客户端都有一个RibbonClientConfiguration配置,初始化RibbonClientConfiguration配置的时候初始化了一些信息,包括是否ping,ribbonclient,还初始化了一个ILoadBalancer对象,调用到了DynamicServerListLoadBalancer方法的enableAndInitLearnNewServersFeature()开启了每30秒去更新一次,eureka服务器的定时任务定时更新BaseLoadBalancer#upServerList对象。
在ribbon负载均衡器中,提供了ping机制,每隔一段时间,就会去ping服务器,由 com.netflix.loadbalancer.IPing 接口去实现。
单独使用ribbon,不会激活ping机制,默认采用DummyPing(在RibbonClientConfiguration中实例化),isAlive()方法直接返回true。
ribbon和eureka集成,默认采用NIWSDiscoveryPing(在EurekaRibbonClientConfiguration中实例化的),只有服务器列表的实例状态为up的时候才会为Alive。
|
在ribbon负载机制中包括 随机、轮询、连接数最少、权重
final ServerStats stats = loadBalancerContext.getServerStats(server);
是自增, loadBalancerContext.noteRequestCompletion(stats, entity, exception, tracer.getDuration(TimeUnit.MILLISECONDS), retryHandler);
是自减。
在没有引入Spring Cloud Eureka等服务治理框架的时候,引入Spring Cloud Ribbon的依赖后,能够自动构建下面这些接口的实现;在同时引入Rureka和Ribbon依赖时,自动化配置会有些不同。
针对个性化的需求,我们可以替换上面的默认配置。
Brixton版本:使用@RibbonClient注解,具体过程可以参考书中内容(没有实践过)
Camden版本:在配置文件中配置,可以通过
hello-server.ribbon.NFLoadBalancerPingClassName=com.netflix.loadbalancer.PingUrl
其中hello-service为服务名,NFLoadBalancerPingClassName参数用来指定具体的IPing接口实现类。
两种参数配置方式:全局配置、指定客户端配置
1、全局配置,只需使用ribbon.
ribbon.OkToRetryOnAllOperations=false ribbon.ConnectTimeout=1000 ribbon.ReadTimeout=10000 ribbon.MaxAutoRetriesNextServer=0
2、客户端配置,采用
hello-server.ribbon.listOfServers=localhost:8001,localhost:8002, 其中hello-service为服务名
(没有服务治理框架的帮助,这样设置)(思考:实现一个不和eureka结合的直接通过ribbon配置调用服务的示例)
当Spring Cloud的应用中同时引入了Spring Cloud Ribbon和Spring Cloud Eureka依赖时,会触发Eureka中实现的对Ribbon的自动化配置。(一切将会变得简单了。。。)
(目的是为了让实例维护策略更加通用,所以使用物理元数据进行负载均衡,而不是使用原生的AWS AMI元数据)
另外也可以通过配置,两者结合使用时也可以禁用Eureka对Ribbon服务实例的维护实现,只需要在配置文件中加入参数: ribbon.eureka.enabled=false
Spring Cloud Ribbon默认实现了区域亲和策略, 所以,我们可以通过Eureka实例的元数据配置来实现区域化的实例配置方案。
思考:为什么需要重试呢?
Spring Cloud Eureka实现的服务治理机制强调了CAP(Consisitency、Availability、Parition tolerance )原理的AP(可用性、可靠性),而Zookeeper这类强调了CP(一致性、可靠性),这也是两者最大的区别。
说明:Eureka为了实现更高的服务可用性,牺牲了一定的一致性,宁愿接受故障实例也不会丢掉健康实例。