1、Ribbon客户端负载均衡原理
对于一个客户端负载均衡实现方案,主要核心三个步骤:
服务发现:能够自动发现所依赖服务的列表服务监听:能够监测到失败的服务,并高效地将失败服务从服务列表中移除负载均衡策略:能够决定如何在多个服务实例中选择一个有效的服务实例,并进行相应的服务请求处理。
Ribbon在具体实现上,有以下组件:
服务器列表(ServerList)
服务器列表就是客户端负载均衡所使用的各服务的服务实例列表。Ribbon在实现上支持3中服务列表方式
静态服务器列表:通过Ribbon的BaseLoadBalancer所提供的setServerList()方法直接进行设置。基于配置的服务器列表:需要在项目配置文件中通过<服务名称>.ribbon.listOfServers进行设置。(如user-service.ribbon.listOfServers=http://127.0.0.1:8000,http://127.0.0.1:8001)基于服务发现的服务器列表:同时使用Ribbon和Eureka时,默认使用该方式,在应用启动时Ribbon就会从Eureka服务器中获取所有注册服务的列表数据,并保持同步。服务器列表过滤(ServerListFilter)
该组件会对原始服务列表使用一定策略进行过滤,并返回有效的服务器列表给客户端负载均衡器使用。
ZoneAffinityServerListFilter:基于区域感知的方式,实现对服务实例的过滤,仅返回与本身所处区域一直的服务提供者实例列表。ServerListSubsetFilter:该过滤器继承自ZoneAffinityServerListFilter,在进行区域感知过滤后,仅返回一个固定大小的服务列表。默认将返回20个服务实例,可以通过ribbon.ServerListSubsetFilter.size进行设置。ZonePreferenceServerListFilter:使用Eureka和Ribbon时默认的过滤器。实现通过配置或者Eureka所属区域来过滤出同区域的服务实例列表。服务实例存活探测(IPing)
用来检测一个微服务实例是否有相应。Ribbon通过该组件来判断所持有的服务实例列表中各服务可用情况,如果检测到某服务实例不存在,则会从列表中及时移除。
PingUrl:通过定期访问指定的URL判断PingConstant:不做任何处理,只返回一个固定值,用来表示该服务是否可用,默认值为true。NoOpPing:不做任何处理,直接返回true,表示该服务器可用,默认策略。DummyPing:直接返回true,但实现了initWithNiwsConfig方法。NIWSDiscoverPing:根据DiscoveryEnabledServer中InstanceInfo的InstanceStatus属性判断,如果该属性的值为InstanceStatus.UP,则表示服务器可用。负载均衡策略(IRule)
负责选择一个最终服务实例地址作为负载均衡处理结果。Ribbon提供的选择策略有轮询、根据相应时间加权、断路器(当Hystrix可用时)等。
负载均衡器(ILoadBalancer)
Ribbon负载均衡主要是通过LoadBalancerClient类实现的,而LoadBalancerClient又将具体处理委托给ILoadBalancer处理。
ILoadBalancer通过配置IRule、IPing等信息,并通过ServerList获取服务器注册列表的信息,默认以每10s的频率想服务列表中每个服务实例发送ping请求,检测服务实例是否存活,最后使用负责均衡策略对ServerListFilter过滤得到最终可用的服务实例列表进行处理,并获取到最终要调用的服务实例,然后交给服务调用器进行调用。
ILoadBalance也是一个接口,提供了3个具体实现,分别是DynamicServerListLoadBalancer、ZoneAwareLoadBalancer和NoOpLoadBalancer。
DynamicServerListLoadBalancer继承自ILoadBalancer基础实现BaseLoadBalancer,在基础的负载均衡功能上增加了运行期间对服务实例动态更新和过滤的功能。
ZoneAwareLoadBalancer则是继承DynamicServerListLoadBalancer,在此基础上增加防止跨区域访问的问题。
服务调用器(RestClient)
就是负载均衡后,Ribbon向服务提供者发起REST请求的工具。
@LoadBalance注解
当给RestTemplate增加了@LoadBalance注解后,LoadBalancerAutoConfiguration就会对该RestTemplate进行处理,在RestTemplate的拦截器列表中添加一个LoadBalancerInterceptor拦截器,当通过RestTemplate进行请求请求时,LoadBalancerInterceptor中的拦截方法就会启动,通过LoadBalancerClient使请求具有负载聚恒功能。
2、Ribbon负载均衡策略及配置RoundRobinRule:轮询策略,默认策略RandomRule:随机策略BestAvailableRule:最大可用策略,即先过滤出故障服务实例后,选择一个当前并发请求数最小的。WeightedResponseTimeRule:带有加权的轮询策略,对各个服务实例响应时间进行加权处理,然后再采用轮询的方式获取相应的服务实例。AvailabilityFilteringRule:可用过滤策略,先过滤出有故障的或并发请求大于阈值的一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选择一个。ZoneAvoidanceRule:区域感知策略,先使用主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例,依次使用次过滤条件列表中的过滤条件对主过滤条件的结果进行过滤,判断最小过滤数和最小过滤百分比,最后对满足条件的服务实例使用轮询方式。配置文件配置方式
代码使用方式
3、直接使用Ribbon API
注意:在使用lbcRestTemplate的时候,不能使用之前@LoadBanlanced的RestTemplate,否则在进行请求时restTempate会把服务实例的逻辑名称当做服务名称来使用。
1、Feign的参数绑定
Spring Cloud对Feign进行了增强,使得Feign支持Spring MVC注解。
Spring MVC常用注解:
@RequestParanm:绑定单个请求参数值@PathVariable:绑定URI模板变量值@RequestHeader:绑定请求头数据@RequestBody:绑定请求的内容区数据并能进行自动类型转换。2、Feign中的继承
虽然Fegin中是可以与正常的Service继承的。但在使用微服务架构开发时有一个原则,就是保持各微服务的自治性。如果进行继承点的话,就会造成服务提供方与服务消费方之间的代码紧耦合。因此不建议Fegin调用接口与业务Service继承相同的Service。
3、Feign与Swagger的冲突
如果项目中使用了Swagger,需要把Swgger升级到2.6.1版本以上。否则会发生冲突,项目无法启动。
Spring Actuator提供了对应用系统自身和监控的继承功能,包含了对应用系统进行配置查看、运行状态监控及相关功能统计等功能。这些监控统计数据通过REST端点方式暴露,并返回JSON数据。
当项目中添加spring-boot-starter-actuator依赖后,Spring Boot在启动系统后就会构建一系列的端点,通过这些端点就可以获取到服务的运行状态。
常用的端点:
/autoconfig:用来获取Spring Boot自动化配置机制所产生的自动化配置信息报告,包含了自动化配置的候选项及每个候选项自动化条件是否满足等信息。/beans:列出所有由Spring Boot创建Bean的配置列表/configprops:用来获取应用中配置的属性信息报告/env:用来获取应用所有可用的环境属性报告,包含环境变量、JVM属性、应用的属性、命令行的参数等。/health:用来报告当前应用的健康状态报告信息,如应用是否启动、磁盘空间。/metrics:用来报告当前应用及宿主主机的各类重要度量指标,如CPU数量、内存信息、线程信息和垃圾回收信息等。/mappings:返回所有控制器映射关系报告。/info:用来返回应用自定义属性配置信息。/shutdown:可以关闭应用。
为什么actuator只看到了health和info呢?原因是actuator默认情况下只暴露了health和info端点,其他端点需要进行配置。
也可以指定开启某个端口