作用
负载均衡
用于客户端负载均衡
集中式负载均衡:消费者与服务提供方中间使用独立方式负载,如F5, NGINX
客户端负载均衡
服务端负责均衡、
客户端,也就是调用方调用负载中心插件,负载中心决定调用哪个服务提供者
常见负载均衡算法
- 轮询
- 随机
- 加权轮询
- 地址hash
- 最小连接数
ribbon模块
| 名 称 | 说 明 | | —- | —- | | ribbon-loadbalancer | 负载均衡模块,可独立使用,也可以和别的模块一起使用。 | | Ribbon | 内置的负载均衡算法都实现在其中。 | | ribbon-eureka | 基于 Eureka 封装的模块,能够快速、方便地集成 Eureka。 | | ribbon-transport | 基于 Netty 实现多协议的支持,比如 HTTP、Tcp、Udp 等。 | | ribbon-httpclient | 基于 Apache HttpClient 封装的 REST 客户端,集成了负载均衡模块,可以直接在项目中使用来调用接口。 | | ribbon-example | Ribbon 使用代码示例,通过这些示例能够让你的学习事半功倍。 | | ribbon-core | 一些比较核心且具有通用性的代码,客户端 API 的一些配置和其他 API 的定义。 |
spring cloud 整合ribbon
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
nacos-discovery依赖ribbon
配置使用
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
调用
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
// RestTemplate调用
//String url = "http://localhost:8020/order/findOrderByUserId/"+id;
//模拟ribbon实现
//String url = getUri("mall-order")+"/order/findOrderByUserId/"+id;
// 添加@LoadBalanced
String url = "http://mall-order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
内核原理
拦截器 LoadBalancerInterceptor
原理就是 拦截调用,把对应服务名替换成对应ip ,端口
@LoadBanlanced注解原理
LoadBalancerAutoConfiguration
Ribbin 相关接口
RibbonClientConfiguration
IClientConfig:ribbon客户端,默认DefaultClientConfigImpl实现
IRule:负责均衡策略默认采用ZoneAvoidanceRule实现
IPing :实例检查策略 DummyPing实现
ServerList 服务实例列表,ConfigurationBasedServerList实现
ServerListFilter:服务实例过滤机制,优先过滤出于请求方同一区域的服务实例
ILoadBalancer :负载均衡ZoneAwareLoadBalancer 实现
负载均衡策略
- RandomRule:
- RetryRule:
- RoundRobinRule:
- AvailabilityFilteringRule:
- BestAvailableRule: 。
- WeightedResponseTimeRule:
- ZoneAvoidanceRule:默认的负载均衡策略,
- NacosRule:
自定义负载均衡策略
实现 IRule接口可以自定义负载均衡策略,重新choose方法
@Slf4j
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String serviceName = loadBalancer.getName();
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
//nacos基于权重的算法
Instance instance = namingService.selectOneHealthyInstance(serviceName);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("获取服务实例异常:{}", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
配置application.yml
# 被调用的微服务名
mall-order:
ribbon:
# 自定义的负载均衡策略(基于随机&权重) 对应方法全路径名
NFLoadBalancerRuleClassName: com.NacosRandomWithWeightRule
利用@RibbonClient指定微服务的放回寺配置负载均衡
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
DruidDataSourceAutoConfigure.class})
//@RibbonClient(name = "mall-order",configuration = RibbonConfig.class)
//配置多个 RibbonConfig不能被@SpringbootApplication的@CompentScan扫描到,否则就是全局配置的效果
@RibbonClients(value = {
// 在SpringBoot主程序扫描的包外定义配置类
@RibbonClient(name = "mall-order",configuration = RibbonConfig.class),
@RibbonClient(name = "mall-account",configuration = RibbonConfig.class)
})
public class MallUserRibbonDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MallUserRibbonDemoApplication.class, args);
}
}
注意
不能写在compentScan扫描到的地方,不让会被所有的ribbonClients共享,最好还是yml配置
饥饿加载
只有在调起的时候才会创建客户端
需要在配置文件中配置
ribbon:
eager-load:
# 开启ribbon饥饿加载
enabled: true
# 配置mall-order使用ribbon饥饿加载,多个使用逗号分隔
clients: mall-order
源码类: RibbonEagerLoadProperties
LoanBalancer
spring cloud LoadBalancer spring cloud 提供的客户端负载均衡,用来替代Ribbon的
Spring官方两种客户端
- RestTemplate
访问rest 服务的客户端,访问http的,依赖jdk的http工具 - WebClient
Spring webFlux 5.0提供,非阻塞的基于响应式变成的http,j
基于Reactor,
引入依赖
<!-- LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- 提供了RestTemplate支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos服务注册与发现 移除ribbon支持-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
注意点: nacos-discory 引入了ribbon,需要排除
原因是:RibbonLoadBalancerClient和BlockingLoadBalancerClient会倾向使用前者
所以需要排除RibbonLoadBalancerClient
也可以在yml配置中排除
#yml中排除ribbon
spring:
application:
name: mall-user-loadbalancer-demo
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 不使用ribbon
loadbalancer:
ribbon:
enabled: false
client的继承关系
使用@LoadBalanced 配置RestTemplate
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
客户端使用
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
String url = "http://mall-order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
}