前面我们讲解了如何对服务进行拆分、如何通过Eureka服务器进行服务注册与发现,那么现在我们来看看,它的负载均衡到底是如何实现的,实际上之前演示的负载均衡是依靠LoadBalancer实现的。

在2020年前的SpringCloud版本是采用Ribbon作为负载均衡实现,但是2020年的版本之后SpringCloud把Ribbon移除了,进而用自己编写的LoadBalancer替代。

那么,负载均衡是如何进行的呢?

负载均衡

实际上,在添加@LoadBalanced注解之后,会启用拦截器对我们发起的服务调用请求进行拦截(注意这里是针对我们发起的请求进行拦截),叫做LoadBalancerInterceptor,它实现ClientHttpRequestInterceptor接口:

@FunctionalInterface
public interface ClientHttpRequestInterceptor {ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException;
}

主要是对intercept方法的实现:

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

我们可以打个断点看看实际是怎么在执行的,可以看到:

服务端会在发起请求时执行这些拦截器。

那么这个拦截器做了什么事情呢,首先我们要明确,我们给过来的请求地址,并不是一个有效的主机名称,而是服务名称,那么怎么才能得到真正需要访问的主机名称呢,肯定是得找Eureka获取的。

我们来看看loadBalancer.execute()做了什么,它的具体实现为BlockingLoadBalancerClient

//从上面给进来了服务的名称和具体的请求实体
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {String hint = this.getHint(serviceId);LoadBalancerRequestAdapter<T, DefaultRequestContext> lbRequest = new LoadBalancerRequestAdapter(request, new DefaultRequestContext(request, hint));Set<LoadBalancerLifecycle> supportedLifecycleProcessors = this.getSupportedLifecycleProcessors(serviceId);supportedLifecycleProcessors.forEach((lifecycle) -> {lifecycle.onStart(lbRequest);});//可以看到在这里会调用choose方法自动获取对应的服务实例信息ServiceInstance serviceInstance = this.choose(serviceId, lbRequest);if (serviceInstance == null) {supportedLifecycleProcessors.forEach((lifecycle) -> {lifecycle.onComplete(new CompletionContext(Status.DISCARD, lbRequest, new EmptyResponse()));});//没有发现任何此服务的实例就抛异常(之前的测试中可能已经遇到了)throw new IllegalStateException("No instances available for " + serviceId);} else {//成功获取到对应服务的实例,这时就可以发起HTTP请求获取信息了return this.execute(serviceId, serviceInstance, lbRequest);}
}

所以,实际上在进行负载均衡的时候,会向Eureka发起请求,选择一个可用的对应服务,然后会返回此服务的主机地址等信息:

自定义负载均衡策略

LoadBalancer默认提供了两种负载均衡策略:

  • RandomLoadBalancer  -  随机分配策略
  • (默认) RoundRobinLoadBalancer  -  轮询分配策略

现在我们希望修改默认的负载均衡策略,可以进行指定,比如我们现在希望用户服务采用随机分配策略,我们需要先创建随机分配策略的配置类(不用加@Configuration):

public class LoadBalancerConfig {//将官方提供的 RandomLoadBalancer 注册为Bean@Beanpublic ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory){String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}

接着我们需要为对应的服务指定负载均衡策略,直接使用注解即可:

@Configuration
@LoadBalancerClient(value = "userservice",      //指定为 userservice 服务,只要是调用此服务都会使用我们指定的策略configuration = LoadBalancerConfig.class)   //指定我们刚刚定义好的配置类
public class BeanConfig {@Bean@LoadBalancedRestTemplate template(){return new RestTemplate();}
}

接着我们在BlockingLoadBalancerClient中添加断点,观察是否采用我们指定的策略进行请求:

发现访问userservice服务的策略已经更改为我们指定的策略了。

LoadBalancer 负载均衡相关推荐

  1. Spring Cloud LoadBalancer(负载均衡)

    简介 了解过Spring Cloud,就知道,之前Spring Cloud中默认的负载均衡组件为ribbon,ribbon是Netflix开源的组件,但是目前已经停止更新了.所以Spring官方推出了 ...

  2. 负载均衡之LoadBalancer

    1.LoadBalancer负载均衡基本实现 2.基本使用 添加LoadBalanced注解 在调用的链接中,将IP和端口替换成应用名称 3.增加 spring-cloud-product-servi ...

  3. SpringCloud之 LoadBalancer和Feign负载均衡

    文章目录 LoadBalancer 负载均衡 一.@LoadBalanced 负载均衡

  4. .net core grpc consul 实现服务注册 服务发现 负载均衡(二)

    在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...

  5. 企业级负载均衡集群——lvs的DR模式(直接路由模式)详细说明

    1.DR模式的原理 其实就是在一台主机上面搭建lvs服务器,设置lvs的工作模式是DR模式,lvs仅仅是一个调度器,它会把客户端的请求转发给后备服务器 DR模式直接由后备服务器把数据返回给客户端,不需 ...

  6. 如何在CentOS 7上使用HAproxy Loadbalancer设置Percona XtraDB集群(负载均衡)

    翻译&转载来源:https://linoxide.com/cluster/setup-percona-cluster-haproxy-centos-7/ 如何在CentOS 7上使用HApro ...

  7. 客户端负载均衡 Loadbalancer

    acos 通过服务发现拿到了所有的可用服务节点列表,但服务请求只能发给一个节点,你知道服务调用是根据什么规则选择目标节点的吗? 负载均衡的作用:了解负载均衡的两大门派,它们分别是网关层负载均衡和客户端 ...

  8. 【官方文档】Nginx负载均衡学习笔记(二)负载均衡基本概念介绍

    简介 负载均衡(Server Load Balancer)是将访问流量根据转发策略分发到后端多台 ECS 的流量分发控制服务.负载均衡可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应 ...

  9. 使用Apache对Tomcat进行负载均衡

    翻译:疯狂的技术宅 原文标题:Load balancing tomcat with Apache 原文链接:http://programmergate.com/loa... 本文首发微信公众号:充实的 ...

  10. saltstack实现haproxy+keepalived负载均衡+高可用(二)

    一键部署haproxy+keepalived实现负载均衡+高可用 实验环境: !!!!    特别注意: www.westos.org为test1的minion名字 test1: 172.25.1.1 ...

最新文章

  1. HDFS配置Kerberos认证
  2. 经典网页设计:10个响应式设计的国外购物网站
  3. antlr4 idea插件_正则都搞不定、我还有Antlr4解析器
  4. Chrome 调试技巧
  5. python 函数可以作为容器对象的元素_11.Python初窥门径(函数名,可迭代对象,迭代器)...
  6. 用c语言编程计算10,计算方法c语言编程.doc
  7. vue 加载数据 影响seu_VUE常见面试题
  8. split和explode有什么区别?
  9. python滚动条翻页爬取数据_[Selenium2+python2.7][Scrap]爬虫和selenium方式下拉滚动条获取简书作者目录并且生成Markdown格式目录...
  10. Exponentially Weighted Averages
  11. Linux中查看bz2压缩文件大小,Linux bz2文件解压与压缩之bzip2命令
  12. 在Cadence中使用ADE进行蒙特卡洛仿真
  13. 微信公众号添加html,微信公众号添加页面模板怎么开通?
  14. 阿里云云计算ACP学习(八)---网络与VPC
  15. C# *未能找到类型“ * ”,请确保已引用包含此类型的程序集。如果此类型为开发项目的一部分,请确保已使用针对当前平台或任意 CPU 的设置成功生成该项目
  16. 3分频器 verilog解析
  17. C#查询自己的公网IP接口(有服务器)
  18. java : word,excel,img,ppt各种文档转换pdf格式以流方式
  19. xp透明膜p系列_一种XPP型超厚医用吸塑包装膜的制作方法
  20. 在JS中利用for...in循环遍历对象

热门文章

  1. 关于百度SDK的返回错误-PERMISSION UNFINISHED
  2. 微信定时发消息Python代码,简单好玩
  3. 四大免费magento支付接口扩展
  4. Python(28)---模块和包的基本概念
  5. 用c语言编写6位计算器,用c语言编写易简计算器.doc
  6. ctf piapiapia(反序列化逃逸)解题记录
  7. 数据结构与算法 知识点总结(中)---线性表,堆栈,队列
  8. 山东省农商行计算机真题,2018山东农商行招聘考试题库:计算机试题三
  9. 【论文阅读】Image Super-Resolution Using Deep Convolutional Networks
  10. 机器学习超详细实践攻略(9):手把手带你使用决策树算法与调参