Java 客户端负载均衡
- 客户端侧负载均衡
在下图中,负载均衡能力算法是由内容中心提供,内容中心相对于用户中心来说,是用户中心的客户端,所以又被称为客户端侧负载均衡
自定义实现Client Random负载均衡
- 获取所有的服务list
- 随机获取需要访问的服务信息
// 自定义客户端负载均衡能力
// 获取所有用户中心服务的实例列表
List<String> targetUris = instances.stream().map(i -> i.getUri().toString() + "/users/{id}").collect(Collectors.toList());
//获取随机实例
int i = ThreadLocalRandom.current().nextInt(targetUris.size());
//调用用户微服务 /users/{userId}
log.info("请求的目标地址:{}", targetUris.get(i));
ResponseEntity<UserDTO> userEntity = restTemplate.getForEntity(
targetUris.get(i),
UserDTO.class, userId
);
Ribbon
什么是Ribbon
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法。
Github: Ribbon 源码
组成接口

内置负载均衡规则

配置方式
- Java 代码配置
/**
* RibbonConfiguration for TODO
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
* @since 2019/7/13
*/
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
/*------------------------------------------------------------*/
/**
* UserCenterRibbonConfiguration for 自定义实现User-center service ribbon client
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
* @since 2019/7/13
*/
@Configuration
@RibbonClient(name = "user-center", configuration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
/*------------------------------------------------------------*/
@Configuration
//@RibbonClient(name = "user-center", configuration = RibbonConfiguration.class) //作用域为 user-center
@RibbonClients(defaultConfiguration = RibbonConfiguration.class) //作用域为全局
public class UserCenterRibbonConfiguration {
}
- 使用配置文件
user-center: # service name
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 规则类的全路径名称
- 对比

- 最佳使用
- 尽量使用属性配置
- 在同一个微服务中尽量保持单一配置,不要混合使用,增加定位复杂性
Tip
在使用Ribbon的时候,配置class一定不能处于启动类的同级目录及其子目录,否则会导致父子上下文重叠问题,带来的结果就是,Ribbon规则会被配置称全局配置规则,从而被所有微服务应用。

The
CustomConfigurationclass must be a@Configurationclass, but take care that it is not in a@ComponentScanfor the main application context. Otherwise, it is shared by all the@RibbonClients. If you use@ComponentScan(or@SpringBootApplication), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the@ComponentScan).
Ribbon 饥饿加载
默认情况下,Ribbon是懒加载,在第一次请求的时候才会创建客户端。
ribbon:
eager-load:
enabled: true # 饥饿加载激活
clients: user-center,xxx,xxx # 为哪些clients开启
使用Ribbon 替代自定义实现
添加依赖(Spring-Cloud-Alibaba-Nacos-Discovery已经依赖了Ribbon,因此不需要额外依赖)
添加注解(只需要在RestTemplate IOC添加
@LoadBalance)/**
* 在Spring 容器中,创建一个对象,类型是{@link RestTemplate}
* 名称/ID 为 restTemplate
* <bean id ="restTemplate" class="XXX.RestTemplate" />
* {@link LoadBalanced} 为RestTemplate整合Ribbon调用
*
* @return restTemplate
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
添加配置,直接使用
ResponseEntity<UserDTO> userEntity = restTemplate.getForEntity(
"http://user-center/users/{userId}",
UserDTO.class, userId
);
扩展Ribbon - 支持Nacos权重
- 实现接口
com.netflix.loadbalancer.IRule - 实现抽象类
com.netflix.loadbalancer.AbstractLoadBalancerRule

@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class NacosWeightRule4Ribbon extends AbstractLoadBalancerRule {
private final NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// 读取配置文件,并初始化 NacosWeightRule4Ribbon
}
@Override
public Server choose(Object key) {
try {
// ILoadBalancer 是Ribbon的入口,基本上我们想要的元素都可以在这个对象中找到
BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
log.info("NacosWeightRule4Ribbon lb = {}", loadBalancer);
// 想要请求的微服务名称
String name = loadBalancer.getName();
// 实现负载均衡算法
// 可得到服务发现相关的API(nacos内部实现)
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
// nacos client 通过基于权重的负载均衡算法,选择一个实例
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("port = {}, weight = {}, instance = {}", instance.getPort(), instance.getWeight(), instance);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("NacosWeightRule4Ribbon {}", e.getMessage());
}
return null;
}
}
@Configuration
@RibbonClients(defaultConfiguration = NacosWeightRule4Ribbon.class) //全局配置
public class UserCenterRibbonConfiguration {
}
拓展Ribbon - 同集群优先
public Server choose(Object key) {
try {
// 获取到配置文件中的集群名称 BJ
String clusterName = nacosDiscoveryProperties.getClusterName();
BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
String serviceName = loadBalancer.getName();
//获取服务发现的相关API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
// 1. 找到指定服务的所有实例 A
List<Instance> instances = namingService.selectInstances(serviceName, true);
// 2. 过滤出相同集群下的所有实例 B
List<Instance> sameClusterInstances = instances.stream()
.filter(instance -> Objects.equals(instance.getClusterName(), clusterName))
.collect(Collectors.toList());
// 3. 如果B为空,则使用 A
List<Instance> instancesChoosen = new ArrayList<>();
if (CollectionUtils.isEmpty(sameClusterInstances)) {
instancesChoosen = instances;
log.warn("发生跨集群调用,name = {},clusterName = {}", serviceName, clusterName);
} else {
instancesChoosen = sameClusterInstances;
}
// 4. 基于权重的负载均衡算法,返回一个实例 A
Instance instance = ExtendBalancer.getHostByRandomWeightOverride(instancesChoosen);
log.info("choose instance is : port = {}, instance = {}", instance.getPort(), instance);
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
log.error(e.getErrMsg());
}
return null;
}
/**
* 调用Nacos内部方法,进行一次包装
*/
class ExtendBalancer extends Balancer {
public static Instance getHostByRandomWeightOverride(List<Instance> hosts) {
return getHostByRandomWeight(hosts);
}
}
扩展Ribbon - 基于元数据的版本控制
Java 客户端负载均衡的更多相关文章
- 笔记:Spring Cloud Ribbon 客户端负载均衡
Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,基于 Netflix Ribbon 实现,通过Spring Cloud 的封装,可以让我们轻松的将面向服 ...
- 基于Spring cloud Ribbon和Eureka实现客户端负载均衡
前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...
- Spring Cloud 2-Ribbon 客户端负载均衡(二)
Spring Cloud Eureka 1.Hello-Service服务端配置 pom.xml application.yml 启动两个service 2.Ribbon客户端配置 pom.xml ...
- spring cloud 使用ribbon简单处理客户端负载均衡
假如我们的multiple服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端口8762修改 ...
- 第四章 客户端负载均衡:Spring Cloud Ribbon
spring cloud ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于Netflix Ribbon 实现.通过Spring Cloud 的封装,可以轻松的将面向服务的R ...
- Spring Cloud Ribbon——客户端负载均衡
一.负载均衡负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性.其意思 ...
- 【SpringCloud微服务实战学习系列】客户端负载均衡Spring Cloud Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的RES模板 ...
- 【Dalston】【第二章】客户端负载均衡(Ribbon)
对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题.在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如 ...
- 客户端负载均衡Feign之一:申明式服务调用Feign入门示例
Spring Cloud提供了Ribbon和Feign作为客户端的负载均衡. 前面使用了Ribbon做客户端负载均衡,使用Hystrix做容错保护,这两者被作为基础工具类框架被广泛地应用在各个微服务的 ...
随机推荐
- 访问类的私有属性(RTTI和模仿类2种方法)
如何访问类的私有属性? 下面以 TPathData 为例,它有一个私有属性 PathData,储存了每一个曲线点,但一般无法修改它,需要利用下面方法,才能访问修改(若有更好的方法,歡迎分享): 一.利 ...
- ThoughtWorks 面试备忘录
ThoughtWorks 面试备忘录 前言 前段时间 ThoughtWorks 在网上和拉勾网合作搞了一次网络招聘,名为抛弃简历!让代码说话!,可谓赚足了眼球,很多程序猿纷纷摩拳擦掌.踊跃提交代码,在 ...
- QT中获取选中的radioButton的两种方法(动态取得控件的objectName之后,对名字进行比较)
QT中获取选中的radioButton的两种方法 QT中要获取radioButton组中被选中的那个按钮,可以采用两种如下两种办法进行: 方法一:采用对象名称进行获取 代码: 1 QRadioBu ...
- Realm_King 之 .NET操作XML完整类
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;u ...
- Win7 访问 数据库 慢
不让TCP/IP调谐拖累网速 在Windows Server 2008工作环境中,下载访问网络中大容量的文件内容时,我们有时会感觉到网络连接速度非常缓慢,严重的时候还会出现不能访问的现象.遭遇这类故障 ...
- php 的mvc开发
至于什么MVC结构,其实就是三个Model,Contraller,View单词的简称,,Model,主要任务就是把数据库或者其他文件系统的数据按 照我们需要的方式读取出来.View,主要负责页面的,把 ...
- fullpage.js使用方法
了解: [1]之所以叫做fullpage,是因为它可以全屏滚动,拥有强大的功能. [2]它依赖于jQuery库,所以在使用fullpage之前先引入jQuery库. 使用: [1]<link r ...
- 从零开始实现放置游戏(七)——实现挂机战斗(5)RMS系统后台参数校验
前面几章实现了在RMS系统中进行数据的增删查改以及通过Excel批量导入.但仍有遗留的问题,比如在新增或编辑时,怪物的生命值.护甲等数据我们可以输入负值,这种数据是不合理且没有意义的.本章我们就实现服 ...
- 基于jsp技术的校园二手交易网站
[项目介绍]基于jsp的校园二手商品交易网站系统使用jsp技术进行开发,项目主要实现了一整套的校园二手交易逻辑, 主要功能如下(包括但不限于,只列出主要功能): 管理员模块 |-----用户管理 ...
- linux 环境 安装jdk tomcat mysql git
1.安装JDK 1.官方下载jdk,linux版本的rpm包 2.安装rz sz ----------编译安装 //安装 cd /tmp wget http://www.ohse.de/uwe/rel ...