Ribbon负载均衡分析
Ribbon使用
ribbon在使用上非常简单,仅仅只sql教程需要在配置类上加入配置即可
@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
调用时,直接使用在eureka中注册的服务java基础教程名进行调用,就可以由ribbon来进行负载均衡了
@GetMapping("/checkAndBegin/{userId}")public Integer findResumeOpenStateEureka(@PathVariable Long userId) {
// List<ServiceInstance> list = discoveryClient.getInstances("lagou-service-resume");
// ServiceInstance serviceInstance = list.get(0);
// String host = serviceInstance.getHost();
// int port = serviceInstance.getPort();String url = "http://zhao-service-resume/resume/openstate/"+userId;System.out.println("从eureka中获取了请求地址"+url);Integer forObject =restTemplate.getForObject(url, Integer.class);return forObject;}
根据要求,zhao-service-resume项目开启多个,并打印请python基础教程求信息,即可发现负载均衡已经实现
另外目前Ribbon的内置负载均衡策略
目前默认使用的是随机负载均衡RandomRule,默认全局生效,但是可以针对不同c#教程的调用服务设置不同的负载均衡策略
zhao-service-resume:ribbon:NFLoadBalancerRuleClassName:
com.netflix.loadbalancer.RandomRule #负载策略调整
同时,可以自定负载均衡策略vb.net教程并配置
Ribbon源码分析
一般而言,自动装配类就是加载配置的入口。
@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})
@EnableConfigurationProperties({RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class})
public class RibbonAutoConfiguration {
}
通过上述配置,我们可以先看看LoadBalancerAutoConfiguration的具体内容
@LoadBalanced@Autowired(required = false)private List<RestTemplate> restTemplates = Collections.emptyList();
此处将自动注入添加了@LoadBalanced注解的RestTemplate对象
同时还注入了一个RestTemplate的定制器RestTemplateCustomizer
@Beanpublic SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {return () -> restTemplateCustomizers.ifAvailable(customizers -> {for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {for (RestTemplateCustomizer customizer : customizers) {customizer.customize(restTemplate);}}});}
继续进入RestTemplateCustomizer的定制器代码,我们发现在定制器中加入了一个拦截器
@Configuration@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")static class LoadBalancerInterceptorConfig {@Beanpublic LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient,LoadBalancerRequestFactory requestFactory) {return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);}@Bean@ConditionalOnMissingBeanpublic RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {return restTemplate -> {List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());list.add(loadBalancerInterceptor);restTemplate.setInterceptors(list);};}}
ClientHttpRequestInterceptor的拦截具体内容为,根据获取到的请求路径和请求地址进行负载均衡
@Overridepublic 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));}
执行负载均衡的代码
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {ILoadBalancer loadBalancer = getLoadBalancer(serviceId);Server server = getServer(loadBalancer, hint);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);}
从这段代码可以看出,第一行根据配置,选出相应的负载均衡策略。第二行就是根据相应的负载均衡策略选择一个服务端进行服务请求,达到负载均衡的目的
最后在BaseLoadBalancer中执行了根据不同的策略选择服务的操作
public Server chooseServer(Object key) {if (counter == null) {counter = createCounter();}counter.increment();if (rule == null) {return null;} else {try {return rule.choose(key);} catch (Exception e) {logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e);return null;}}}
考虑完了上面的主逻辑之后,还有一个问题,就是服务列表是什么时候获取到的。
在RibbonAutoConfigration中注入了SpringClientFactory,而SpringClientFactory又注入了RibbonClientConfiguration
public SpringClientFactory() {super(RibbonClientConfiguration.class, NAMESPACE, "ribbon.client.name");}
RibbonClientConfiguration中进行了注入客户端操作的相关操作,包括负载均衡策略,客户端配置,服务列表等,其中最重要的就是如何获取和更新服务列表
@ConditionalOnMissingBean@SuppressWarnings("unchecked")public ServerList<Server> ribbonServerList(IClientConfig config) {if (this.propertiesFactory.isSet(ServerList.class, name)) {return this.propertiesFactory.get(ServerList.class, config, name);}ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();serverList.initWithNiwsConfig(config);return serverList;}@Bean@ConditionalOnMissingBeanpublic ServerListUpdater ribbonServerListUpdater(IClientConfig config) {return new PollingServerListUpdater(config);}@Bean@ConditionalOnMissingBeanpublic ILoadBalancer ribbonLoadBalancer(IClientConfig config,ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,IRule rule, IPing ping, ServerListUpdater serverListUpdater) {if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) {return this.propertiesFactory.get(ILoadBalancer.class, config, name);}return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList,serverListFilter, serverListUpdater);}
在ribbonList方法中并未有获取serverList的操作,在ribbonLoadBalancer中进行了使用,那么究竟怎么一回事呢?实际上是在ZoneAwareLoadBalancer的父类DynamicServerListLoadBalancer中进行了重新的赋值并且执行了定时任务进行更新。
void restOfInit(IClientConfig clientConfig) {boolean primeConnection = this.isEnablePrimingConnections();// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()this.setEnablePrimingConnections(false);enableAndInitLearnNewServersFeature();updateListOfServers();if (primeConnection && this.getPrimeConnections() != null) {this.getPrimeConnections().primeConnections(getReachableServers());}this.setEnablePrimingConnections(primeConnection);LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());}
首先通过updateAction.doUpdate();更新,然后通过getRefreshExecutor()进行获取
@Overridepublic synchronized void start(final UpdateAction updateAction) {if (isActive.compareAndSet(false, true)) {final Runnable wrapperRunnable = new Runnable() {@Overridepublic void run() {if (!isActive.get()) {if (scheduledFuture != null) {scheduledFuture.cancel(true);}return;}try {updateAction.doUpdate();lastUpdated = System.currentTimeMillis();} catch (Exception e) {logger.warn("Failed one update cycle", e);}}};scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(wrapperRunnable,initialDelayMs,refreshIntervalMs,TimeUnit.MILLISECONDS);} else {logger.info("Already active, no-op");}}
欢迎搜索关注本人与朋友共同开发的微信面经小程序【大厂面试助手】和公众号【微瞰技术】,以及总结的分类面试题https://github.com/zhendiao/JavaInterview
Ribbon负载均衡分析相关推荐
- SpringCloud源码:Ribbon负载均衡分析
本文主要分析 SpringCloud 中 Ribbon 负载均衡流程和原理. SpringCloud版本为:Edgware.RELEASE. 一.时序图 和以前一样,先把图贴出来,直观一点: 二.源码 ...
- JavaEE进阶知识学习-----SpringCloud(六)Ribbon负载均衡
Ribbon负载均衡 Ribbon概述 Spring Cloude Ribbon是基于Netfilx Ribbon实现的一套客户端 负载均衡的工具,简单说,Ribbon是Netfilix发布的开源项目 ...
- SpringCloud[04]Ribbon负载均衡服务调用
文章目录 Ribbon负载均衡服务调用 1. 概述 1. Ribbon是什么 2. Ribbon能做什么 2. Ribbon负载均衡演示 1. 架构说明 2. Ribbon的POM依赖 3. Rest ...
- spring cloud中通过配置文件自定义Ribbon负载均衡策略
2019独角兽企业重金招聘Python工程师标准>>> spring cloud中通过配置文件自定义Ribbon负载均衡策略 博客分类: 微服务 一.Ribbon中的负载均衡策略 1 ...
- SpringCloud:Ribbon负载均衡(基本使用、 负载均衡、自定义配置、禁用 Eureka 实现 Ribbon 调用)
现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现在的问题,所有的微服务汇集到了 Eureka 之 ...
- 详解Eureka服务注册与发现和Ribbon负载均衡【纯理论实战】
Eureka服务注册与发现 Eureka简介 在介绍Eureka前,先说一下CAP原则 CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性). Availability ...
- 最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇
文章目录 前言 一.Ribbon核心概念 二.服务器端负载均衡和Riboon客户端负载均衡 1.服务器端负载均衡: 2.Riboon客户端负载均衡: 三.Ribbon策略 四.Ribbon配置使用 五 ...
- Ribbon负载均衡原理,Feign是如何整合Ribbon的?
文章目录 1. 什么是负载均衡? 2. Ribbon的使用 ①:自定义负载均衡策略 ②:Ribbon的饥饿加载 3. Ribbon的负载均衡原理 ①:收集带有@LoadBalanced注解的RestT ...
- SpringCloud的Ribbon负载均衡
Spring Cloud Ribbon相关学习: 简介 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具. 简单的说,Ribbon是Netflix ...
- SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)...
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册 ...
最新文章
- tf.keras.activations.softmax 激活函数 示例
- SpringBoot下的模板技术Thymeleaf详解
- cocos2d-x for android配置 运行 Sample on Linux OS
- TCP第四次挥手为什么要等待2MSL
- C# 中 NPOI 库读写 Excel 文件的方法【摘】
- 协鑫集成携中国成套工程在核灾区建立1GW光伏电站
- 数学建模 聚类模型
- 智能一代云平台(三十三):log4j日志研究
- 自动化CodeReview - ASP.NET Core请求参数验证
- [转载]幂等和高并发在电商系统中的使用
- apache 支持.htaccess 解决Internal Server Error The server 错误
- 挑战程序设计竞赛(第一章)
- LCD1602A模块的应用
- 一个粗糙的js分页判断
- SQL Server 监视(Monitoring)体系架构
- Spring Cloud实战(二)-Spring Cloud Eureka
- 前端——面试(苏小妍)
- 【量化交易】 量化因子 情绪类因子计算
- ipad服务器的显示器,Air Display怎么用 iPad怎么分屏显示 值得收藏
- 企业怎样顺利实施ERP管理系统?