Ribbon核心工作原理

Ribbon核心工作原理

1.Ribbon的核心接口

接口描述默认实现
IClientConfig定义 Ribbon 中管理配置的接口DefaultClientConfiglmpl
IRule定义 Ribbon 中负载均衡策略的接口ZoneAvoidanceRule
IPing定义定期 ping 服务检查可用性的接口DummyPing
ServerList定义获取服务列表方法的接口ConfigurationBasedServerList
ServerListFilter定义特定期望获取服务列表方法的接口ZonePreferenceServerListFilter
ILoadBalancer定义负载均衡选择服务的核心方法的接口ZoneAwareLoadBalancer
ServerListUpdater为 DynamicServerListLoadBalancer 定义动态 更新
服务列表的接口
PollingServerListUpdater

2.LoadBalancerClient-负载均衡的基石

/**
 * Represents a client side load balancer
 * @author Spencer Gibb
 */
public interface LoadBalancerClient extends ServiceInstanceChooser {
	// 使用来自LoadBalancer的ServiceInstance对指定对象执行请求
	<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
	// 使用来自LoadBalancer的ServiceInstance对指定对象执行请求
	<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
	// 使用真实的主机和端口创建适当的URI
	URI reconstructURI(ServiceInstance instance, URI original);
}
public interface ServiceInstanceChooser {

    /**从LoadBalancer中为指定服务选择一个ServiceInstance
     * Choose a ServiceInstance from the LoadBalancer for the specified service
     */
    ServiceInstance choose(String serviceId);
}

这两个类奠定了从负载均衡器中选取服务实例,用服务实例构建真实服务地址,以及发送请求的底层架构基础。

3.LoadBalancerAutoConfiguration-负载均衡配置的自动装配

@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
    /***
    *从类的注解就可以看出,它配置加载的时机一是当前工程环境必须有 RestTemplate 的实 例,
二是在工程环境中必须初始化了 LoadBalancerClient 的实现类
    **/
	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

	@Bean
	public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
			final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
		return () -> restTemplateCustomizers.ifAvailable(customizers -> {
            for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
                for (RestTemplateCustomizer customizer : customizers) {
                    customizer.customize(restTemplate);
                }
            }
        });
	}

	@Autowired(required = false)
	private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
	/**
	*LoadBalancerRequestFactory 用于创建 LoadBalancerRequest和LoadBalancerlnterceptor 使用,它在低版本中是没有的.LoadBalancerInterceptorConfig 中 则 维 护 了 Load- Balancerinterceptor 与RestTemplateCustomizer 的实例 , 它们的作用如下:
	□ LoadBalancerlnterceptor : 拦截每一次 HTTP 请求,将请求绑定进 Ribbon 负载均衡的 生命周期。
	□ RestTemplateCustomizer: 为每个 RestTemplate 绑定 LoadBalancerlnterceptor 拦截器。
	**/
	@Bean
	@ConditionalOnMissingBean
	public LoadBalancerRequestFactory loadBalancerRequestFactory(
			LoadBalancerClient loadBalancerClient) {
		return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
	}

	@Configuration
	@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
	static class LoadBalancerInterceptorConfig {
		@Bean
		public LoadBalancerInterceptor ribbonInterceptor(
				LoadBalancerClient loadBalancerClient,
				LoadBalancerRequestFactory requestFactory) {
			return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
		}

		@Bean
		@ConditionalOnMissingBean
		public RestTemplateCustomizer restTemplateCustomizer(
				final LoadBalancerInterceptor loadBalancerInterceptor) {
			return restTemplate -> {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                        restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            };
		}
	}
......
}

在这里就很明确了,通过 loadBalancerClient生成 LoadBalancerInterceptor并为每个 RestTemplate 绑定 LoadBalancerlnterceptor 拦截器。

4.LoadBalancerInterceptor-负载均衡拦截器

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

	private LoadBalancerClient loadBalancer;
	private LoadBalancerRequestFactory requestFactory;

.....
    // 执行拦截器
	@Override
	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
			final ClientHttpRequestExecution execution) throws IOException {
		final URI originalUri = request.getURI();
		String serviceName = originalUri.getHost();
		Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
		return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
	}
}

利用 ClientHttpRequestlnterceptor 来对每次 HTTP 请求进行拦截的,此类是 Spring 中维护的请求拦截器,实现它的 intercept 方法就可以使请求进入方法体,从而做一些处 理。可以看出这里把请求拦截下来之后使用了 LoadBalancerClientexecute 方法来处理请求,由于我 们在 RestTemplate 中使用的 URI 是形如 http://myservice/path/to/service 的,所以这里的 getHost() 方法实 际 取 到 的 就 是 服 务 名 myservice。LoadBalancerClient 接 口 只 有 一 个 实 现 类 , 即RibbonLoadBalancerClient

4.RibbonLoadBalancerClient-Ribbon的负载均衡实现

public class RibbonLoadBalancerClient implements LoadBalancerClient {
.....
    @Override
	public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
    	// 获取具体的服务实例 就是根基服务的实例名字获取服务的相关元数据信息
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
    	// Server 就是具体服务实例的封装 
    	// 就是发生负载均衡过程的地方
		Server server = getServer(loadBalancer);
		if (server == null) {
			throw new IllegalStateException("No instances available for " + serviceId);
		}
		RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
				serviceId), serverIntrospector(serviceId).getMetadata(server));
		// 执行请求
		return execute(serviceId, ribbonServer, request);
	}
    
    protected Server getServer(ILoadBalancer loadBalancer) {
		if (loadBalancer == null) {
			return null;
		}
		return loadBalancer.chooseServer("default"); // default 就是默认的负载均衡算法的key
	}
    /********************************非本类的实现********************************/
     public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            try { 
                // 我们发现, rule.choose(key) 中的 rule 其实就是 IRule, 至此,拦截的HTTP 请求与负载均 衡策略得以关联起来
                return rule.choose(key);
            } catch (Exception e) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
                return null;
            }
        }
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[为什么要学习Spring Cloud微服务] SpringCloud作为主流微服务框架,已成为各互联网公司的首选框架,国内外企业占有率持续攀升,是Java工程师的必备技能。就连大名鼎鼎的阿里巴巴dubbo也正式更名为Spring Cloud Alibaba,成为了Spring Cloud 微服务中的一个子模块。Spring Cloud是企业架构转型、个人能力提升、架构师进阶的不二选择。 【推荐你学习这门课的理由】 1、本课程总计29课时,从微服务是什么、能够做什么开始讲起,绝对的零基础入门 2、课程附带全部26个项目源码,230页高清PDF正版课件 【课程知识梳理】 1、先讲解了什么是单体架构、什么是微服务架构、他们之间有什么区别和联系,各自有什么优缺点。 2、从本质入手,使用最简单的Spring Boot搭建微服务,让你认清微服务是一种思想和解决问题的手段,而不是新兴技术。 3、讲解Spring BootSpring Cloud 微服务架构之间的联系,原生的RestTemplate工具,以及Actuator监控端点的使用。4、带着微服务所带来的各种优缺点,为大家引入服务发现与注册的概念和原理,从而引入我们的第一个注册中心服务Eureka。5、引入负载均衡的理念,区分什么是服务端负载均衡,什么是客户端负载均衡,进而引入Ribbon负载均衡组件的详细使用。6、为了解决微服务之间复杂的调用,降低代码的复杂度,我们引入了Feign声明式客户端,让你几行代码搞定服务的远程调用。7、最后为大家介绍了整个微服务体系应该包含什么,学习路线是什么,应该学习什么。 【学习方法】 每一节课程均有代码,最好的方式是静下心来,用一天的时间,或者两个半天时间来学习。一边听我的讲解,一边使用我提供的项目代码进行观察和运行。只要你能跟住我的节奏,你就可以搞定微服务

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值