SpringCloud源码研读(四):ribbon

Ribbon运行时Bean做了命名空间隔离,给每个服务方定义一个独立的bean上下文。这样做是为了支持对某一个服务单独配置负载。比如负载算法,是否重试等,也可以为每一个服务实例化一个服务发现逻辑,可以最大化地将自由交给实现方。

核心领域对象

  • SpringClientFactory是Ribbon全局唯一的bean工厂,只有一个实例。通过getInstances(String name, Class type)可以创建不同的命名空间(name)的不同类型对象(type)实例。

  • 对@FeignClient声明的服务而言,每一个name都有一个FeignLoadBalancer实例。FeignLoadBalancer通过DynamicServerListLoadBalancer执行具体的负载均衡工作。

  • DynamicServerListLoadBalancer承载了Ribbon运行时负载均衡的全部逻辑,包括负载选择,重试等等。

  • ConsulServerList是一个逻辑含义的服务,指向一组具有相同业务功能的物理服务。是负载均衡选择的基础。

  • ConsulServer是一个物理含义的服务,指向服务的一个具体的运行实例。

在这里插入图片描述

bean注册

Ribbon注册的引入链为

RibbonAutoConfiguration
   => SpringClientFactory
   => @RibbonClients
      => RibbonClientConfigurationRegistrar

SpringClientFactory懒加载

Ribbon运行时依赖的类并没有在spring Application启动时初始化,而是在使用时懒加载。在需要时,SpringClientFactory基于RibbonClientConfiguration创建对应的bean实例。SpringClientFactory继承了NamedContextFactory。

Feign运行时,SynchronousMethodHandler.executeAndDecode(RequestTemplate)调用LoadBalancerFeignClient实现负载均衡。分析LoadBalancerFeignClient代码可以看出懒加载的过程:

//LoadBalancerFeignClient
@Override
public Response execute(Request request, Request.Options options) throws IOException {
	try {
		URI asUri = URI.create(request.url());
		String clientName = asUri.getHost();
		URI uriWithoutHost = cleanUrl(request.url(), clientName);
		FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
				this.delegate, request, uriWithoutHost);
//1. 懒加载IClientConfig
		IClientConfig requestConfig = getClientConfig(options, clientName);
		return lbClient(clientName) //2. 懒加载FeignLoadBalancer
				.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
	}
	catch (ClientException e) {
		IOException io = findIOException(e);
		if (io != null) {
			throw io;
		}
		throw new RuntimeException(e);
	}
}
  1. ribbon追求为每个服务独立配置负载均衡策略,所以每个服务都有自己的IClientConfig实例。
  2. 从CachingSpringLoadBalancerFactory获取FeignLoadBalancer,没有会从SpringClientFactory创建。

SpringClientFactory创建ILoadBalancer时调用堆栈:

RibbonClientConfiguration.ribbonLoadBalancer(IClientConfig,ServerList,ServerListFilter,IRule,IPing,ServerListUpdater) 
ZoneAwareLoadBalancer.<init>(IClientConfig,IRule,IPing,ServerList,ServerListFilter,ServerListUpdater) 
DynamicServerListLoadBalancer.<init>(IClientConfig,IRule,IPing,ServerList,ServerListFilter,ServerListUpdater) 
ConsulServerList.getUpdatedListOfServers()
ConsulServerList.getServers()
ConsulClient.getHealthServices(String,String,boolean,QueryParams,String) 
HealthConsulClient.getHealthServices(String,String,boolean,QueryParams,String)
ConsulRawClient.makeGetRequest(String,UrlParameters[]) 

在创建DynamicServerListLoadBalancer时,Ribbon会调用consul server查询service的实例信息。同时创建心跳检测ServerListUpdater。

运行时调用

DynamicServerListLoadBalancer在运行时执行负载均衡策略。
在这里插入图片描述

负载均衡策略

负载均衡策略由IRule执行。
在这里插入图片描述
Ribbon 进行客户端负载均衡时,如果被调用方起了多个实例,对于本地调试很麻烦。解决方法:在 bootstrap.properties 文件中加入以下配置:
spring.cloud.consul.ribbon.enabled=false
示例:

hello-world.ribbon.listOfServers=192.168.26.183:8777
{替换成需要调用的服务名}.ribbon.listOfServers={替换成需要调用服务的IP:端口号}

健康检查

PollingServerListUpdater定期查询consul server检查service的各实例健康情况。

Ribbon和Spring Cloud Consul: http://blog.sina.com.cn/s/blog_72ef7bea0102xft7.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值