当前位置:网站首页>Ribbon负载均衡服务调用
Ribbon负载均衡服务调用
2022-06-26 05:26:00 【RB_VER】
概述
spring cloud ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。
简单地说,ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。ribbon客户端组件提供一系列完善的配置项如连接超时、重试等。简单地说,就是在配置文件中列出load balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。
负载均衡就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡软件有Nginx、LVS等。
Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由Nginx实现转发请求。即负载均衡是由服务端实现的。(集中式LB)
Ribbon是本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程过程调用技术。(进程内LB)
集中式LB:即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5,也可以是软件,如Nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方。
进程内LB:将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon负载均衡和Rest调用
Ribbon其实就是一个负载均衡的客户端组件,它可以和其他所需请求的客户端结合使用。

Ribbon工作时分两步:
第一步先选择Eureka Server,它优先选择在同一个区域内负责较少的server。
第二步再根据用户指定的策略,在从server获取到的服务注册列表中选择一个地址。
spring-cloud-starter-netflix-eureka-client自带了spring-cloud-starter-ribbon引用。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Ribbon默认自带的负载规则
IRule接口:根据特定算法中从服务列表中选取一个要访问的服务。
实现IRule接口的自带常用规则:
- com.netflix.loadbalancer.RoundRobinRule:轮询。(默认)
- com.netflix.loadbalancer.RandomRule:随机。
- com.netflix.loadbalancer.RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务。
- WeightedResponseTimeRule:对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择。
- BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。
- AvailabilityFilteringRule:先过滤故障实例,再选择并发较小的实例。
- ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器。
负载规则替换
自定义配置类不能放在@ComponentScan所扫描的当前包以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。
cloud-consumer-order80模块目录结构:
MySelfRule
package com.qrxqrx.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MySelfRule {
@Bean
public IRule myRule() {
return new RandomRule();
}
}
OrderMain80
package com.qrxqrx.springcloud;
import com.qrxqrx.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
Ribbon默认负载均衡算法原理
rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标
每次服务重启后rest接口计数从1开始。
RoundRobinRule源码分析
RandomRule的choose方法:
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
} else {
Server server = null;
int count = 0;
while(true) {
if (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
if (upCount != 0 && serverCount != 0) {
int nextServerIndex = this.incrementAndGetModulo(serverCount);
server = (Server)allServers.get(nextServerIndex);
if (server == null) {
Thread.yield();
} else {
if (server.isAlive() && server.isReadyToServe()) {
return server;
}
server = null;
}
continue;
}
log.warn("No up servers available from load balancer: " + lb);
return null;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: " + lb);
}
return server;
}
}
}
Ribbon手写轮询算法
在cloud-provider-payment8001和cloud-provider-payment8002中修改controller
@GetMapping(value = "/payment/lb")
public String getPaymentLB() {
return serverPort;
}
修改cloud-consumer-order80模块,注释掉配置类的@LoadBalanced
@Configuration
public class ApplicationContextConfig {
@Bean
//@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
实现LoadBalancer
package com.qrxqrx.springcloud.lb;
import org.springframework.cloud.client.ServiceInstance;
import java.util.List;
public interface LoadBalancer {
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
实现
package com.qrxqrx.springcloud.lb;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class MyLB implements LoadBalancer {
private AtomicInteger atomicInteger = new AtomicInteger(0);
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
int index = getAndIncrement() % serviceInstances.size();
return serviceInstances.get(index);
}
public final int getAndIncrement() {
int current;
int next;
do {
current = this.atomicInteger.get();
next = current >= 2147483647 ? 0 : current + 1;
} while(this.atomicInteger.compareAndSet(current,next));
System.out.println("第"+next+"次访问");
return next;
}
}
修改OrderController
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if (instances == null || instances.size() <= 0) {
return null;
}
ServiceInstance serviceInstance = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
边栏推荐
- 第九章 设置结构化日志记录(一)
- Leetcode114. 二叉树展开为链表
- 【ARM】在NUC977上搭建基于boa的嵌入式web服务器
- Sentimentin tensorflow_ analysis_ cell
- Keras actual combat cifar10 in tensorflow
- [red team] what preparations should be made to join the red team?
- Ad tutorial series | 4 - creating an integration library file
- Excellent learning ability is your only sustainable competitive advantage
- data = self._data_queue.get(timeout=timeout)
- vscode config
猜你喜欢

Could not get unknown property ‘*‘ for SigningConfig container of type org. gradle. api. internal

The parameter field of the callback address of the payment interface is "notify_url", and an error occurs after encoding and decoding the signed special character URL (,,,,,)

Introduction to alluxio
![[upsampling method opencv interpolation]](/img/6b/5e8f3c2844f0cbbbf03022e0efd5f0.png)
[upsampling method opencv interpolation]

LeetCode_ Binary search tree_ Simple_ 108. convert an ordered array to a binary search tree

创建 SSH 秘钥对 配置步骤

Create SSH key pair configuration steps
Technical problems to be faced in mobile terminal im development

Introduction to GUI programming to game practice (I)

The difference between get and post in small interview questions
随机推荐
递归遍历目录结构和树状展现
The best Chinese open source class of vision transformer, ten hours of on-site coding to play with the popular model of Vit!
Introduction to GUI programming to game practice (II)
无线网络存在的安全问题及现代化解决方案
Wechat team sharing: technical decryption behind wechat's 100 million daily real-time audio and video chats
【上采样方式-OpenCV插值】
【MYSQL】MySQL 百万级数据量分页查询方法及其优化
Leetcode114. Expand binary tree into linked list
Tp5.0 framework PDO connection MySQL error: too many connections solution
Redis discovery bloom filter
Leetcode513. Find the value in the lower left corner of the tree
Red team scoring method statistics
Secondary bootloader about boot28 Precautions for ASM application, 28035
【ARM】讯为rk3568开发板buildroot添加桌面应用
Anaconda creates tensorflow environment
[activity recommendation] cloud native, industrial Internet, low code, Web3, metauniverse... Which is the architecture hot spot in 2022
Vie procédurale
Positioning setting horizontal and vertical center (multiple methods)
Could not get unknown property ‘*‘ for SigningConfig container of type org. gradle. api. internal
Baidu API map is not displayed in the middle, but in the upper left corner. What's the matter? Resolved!