定制软件【微服务】2、一篇文章详解 Ribbon 负载均衡

Ribbon 负载均衡

📝 【上篇文章】
🔖 用 定制软件做注册中心
🔖 user-service 定制软件的多个实例向 Eureka 定制软件注册自己的服务信息
🔖 order-service 通过服务名(如 userservice)获取 Eureka 定制软件注册中心里面指定服务名(如 userservice)定制软件的服务列表
🔖 定制软件通过一个服务名(如 userservice)定制软件可以获取到多个服务地址信息
❓ 究竟通过哪个地址信息发送请求呢 ❓
🔖 这通过【负载均衡】来决定

一、负载均衡原理(debug 源码)

(1) 基本介绍



📖 @LoadBalanced 注解表示:将来 RestTemplate 发起的请求要被 ribbon 拦截

📖 这个拦截操作是通过 LoadBalancerInterceptor 完成的
📖 它是 SpringCloud 中的拦截器org.springframework.cloud.client.loadbalancer
📖 LoadBalancerInterceptorClientHttpRequestInterceptor 接口的实现类



(2) 打断点

① LoadBalancerInterceptor.java - intercept()

public 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);	// this.loadBalancer: RibbonLoadBalancerClient	// 进入 this.loadBalancer.execute 方法	return this.loadBalancer.execute(serviceName,			this.requestFactory.createRequest(request, body, execution));}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

② RibbonLoadBalancerClient.java - execute()

public <T> T execute(String serviceId, LoadBalancerRequest<T> request)		throws IOException {	// serviceId: 服务名	return execute(serviceId, request, null);}
  • 1
  • 2
  • 3
  • 4
  • 5

③ RibbonLoadBalancerClient.java - execute()

🔋 调用 RibbonLoadBalancerClient 重载的另一个 execute() 方法

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)		throws IOException {	// 通过服务名获取负载均衡器	// loadBalancer 的 allServerList 中包含服务地址信息	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);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16


④ RibbonLoadBalancerClient.java - getServer()

protected Server getServer(ILoadBalancer loadBalancer, Object hint) {	if (loadBalancer == null) {		return null;	}	// Use 'default' on a null hint, or just pass it on?	return loadBalancer.chooseServer(hint != null ? hint : "default");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

⑤ ZoneAwareLoadBalancer.java - chooseServer()

🔋 调用父类的 chooseServer()

⑥ BaseLoadBalancer.java - chooseServer()

public Server chooseServer(Object key) {    if (counter == null) {        counter = createCounter();    }    counter.increment();    // rule 默认是 ZoneAvoidanceRule 类型, 不为 null    if (rule == null) {        return null;    } else {        try {            // 根据 key 选择一个活着的的服务            return rule.choose(key);        } catch (Exception e) {            logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);            return null;        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18


⑦ RibbonLoadBalancerClient.java - execute()

🔋 拿真实的服务地址替换服务名

(3) 流程

二、负载均衡策略

(1) 负载均衡策略

📝 Ribbon 的负载均衡策略是通过一个叫做 IRule 的接口来定义的,每个实现类是一种策略

(2) 调整负载均衡策略

📝 有种方式指定 IRule 实现,进而修改负载均衡规则

① 注入(@Bean)自己需要的负载均衡策略(IRule)

全局:整个微服务

  @Bean  public IRule iRule() {      return new RandomRule();  }
  • 1
  • 2
  • 3
  • 4

📝 整个微服务发送的请求都通过【随机】方式负载均衡

② yaml 文件指定对某个指定微服务发送请求的使用采用指定的负载均衡策略

局部:只对某个微服务有作用

userservice: # 该微服务向 userservice 发送的请求使用【随机】负载均衡  ribbon:   NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  • 1
  • 2
  • 3

(3) 饥饿加载

📝 Ribbon 默认是采用懒加载 【第一次访问时才会创建 LoadBalanceClient,请求时间会很长】
📝 饥饿加载会让 LoadBalanceClient 在项目启动时被创建,进而降低第一次访问的耗时

ribbon:  eager-load:    enabled: true # 开启饥饿加载    clients:      - userservice # 指定对哪些微服务进行饥饿加载
  • 1
  • 2
  • 3
  • 4
  • 5

📖 根据 Bilibili 黑马程序员进行学习
📖 如有错误,请不吝赐教哦

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发