第 2 节 Ribbon负载均衡
2.1 关于负载均衡
负载均衡一般分为服务器端负载均衡和客户端负载均衡
所谓服务器端负载均衡,比如Nginx、F5这些,请求到达服务器之后由这些负载均衡器根据一定的算法将请求路由到目标服务器处理。
所谓客户端负载均衡,比如我们要说的Ribbon,服务消费者客户端会有一个服务器地址列表,调用方在请求前通过一定的负载均衡算法选择一个服务器进行访问,负载均衡算法的执行是在请求客户端进行。
Ribbon是Netflix发布的负载均衡器。Eureka一般配合Ribbon进行使用,Ribbon利用从Eureka中读取到服务信息,在调用服务提供者提供的服务时,会根据一定的算法进行负载。
2.2 Ribbon高级应用
需求: 复制商品微服务9001,在9000和9001编写Controller,返回服务实例端口。
Page微服务中通过负载均衡策略调用lagou-service-product的controller
在微服务中使用Ribbon不需要额外导入依赖坐标,微服务中引入过eureka-client相关依赖,会自动引入Ribbon相关依赖坐标。
代码中使用如下,在RestTemplate上添加对应注解即可
@EnableDiscoveryClient //表示可以向注册中心注册服务,不止在Eureka环境
public class PageApplication {
public static void main(String[] args) {
SpringApplication.run(PageApplication.class, args);
}
// 诸如RestTemplate ,封装好的HttpClient
@Bean
@LoadBalanced //Ribbon负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
创建lagou-serivce-product-9001微服务,创建ServerConfigController,定义方法返回当前微服务所使用的容器端口号
修改服务提供者api返回值,返回当前实例的端口号,便于观察负载情况
@RestController
@RequestMapping("/server")
public class ServerConfigController {
@Value("${server.port}")
private String serverPort;
@requestMapping("query")
public String findServerPort(){
return serverPort;
}
}
在pageService调用查询端口号的接口
@RequestMapping("/getPort")
public String getProductServerPort(){
String url = "http://lagou-service-product/server/query";
return restTemplate.getForObject(url,String.class);
}
在浏览器上访问pageService的getPort接口,查看返回值
2.3 Ribbon负载均衡策略
Ribbon内置了多种负载均衡策略,内部负责复杂均衡的顶级接口为 com.netflix.loadbalancer.IRule ,
接口简介:
ctrl + n 查找Irule接口
package com.netflix.loadbalancer;
/**
* Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of
* as a Strategy for loadbalacing. Well known loadbalancing strategies include
* Round Robin, Response Time based etc.
*
* @author stonse
*
*/
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
按住ctrl+alt + B 查看其实现的子类
右键选择
按住ctrl+alt +b 选择所有实现类出现下图
修改负载均衡策略:
#针对的被调用方微服务名称,不加就是全局生效
lagou-service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机策略
lagou-service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #轮询策略
2.4 Ribbon核心源码剖析
Ribbon工作原理:
老规矩:SpringCloud充分利用了SpringBoot的自动装配特点,找spring.factories配置文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
LoadBalancerAutoConfiguration 类中配置
装配验证:
自动注入:
注入restTemplate定制器:
为retTemplate对象设置loadBalancerInterceptor
到这里,我们明白,添加了注解的RestTemplate对象会被添加一个拦截器LoadBalancerInterceptor,该拦截器就是后续拦截请求进行负载处理的。