前言:
软件系统开发定制本篇文章主要介绍Ribbon软件系统开发定制负载均衡的使用,软件系统开发定制策略及原理,软件系统开发定制希望能加深自己的印象软件系统开发定制以及帮助各位大佬🤞🤞
软件系统开发定制如果文章有什么需要改进的地方还请大佬多多指正✨✨
小威在这里先感谢各位大佬了🎊🎊
文章目录
🚗Ribbon负载均衡使用
接着上一篇文章的来,运用负载均衡的注解 @LoadBalanced进行管理
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
- 1
- 2
- 3
- 4
- 5
🚜Ribbon项目使用流程
- 拦截我们的RestTemplate请求http://userservice/user/1
- RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
- DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
- RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求
🚓Ribbon负载均衡分析
负载均衡拦截器实现客户端http请求拦截器(ClientHttpRequestInterceptor)并重写方法
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor { private LoadBalancerClient loadBalancer; private LoadBalancerRequestFactory requestFactory; public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) { this.loadBalancer = loadBalancer; this.requestFactory = requestFactory; } public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) { this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer)); } public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { URI originalUri = request.getURI(); String serviceName = originalUri.getHost(); Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri); return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
找到Eureka服务列表并根据负载均衡算法选取一个服务
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);//根据服务名称找Eureka服务列表 Server server = this.getServer(loadBalancer, hint);//根据负载均衡算法从Eureka的server列表中选出一个 if (server == null) { throw new IllegalStateException("No instances available for " + serviceId); } else { RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server)); return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。
在BaseLoadBalancer.class的类下,利用IRule实现负载均衡的策略
跟进上面的getServer方法,继续跟踪源码在BaseLoadBalancer类下找到chooseServer方法
public Server chooseServer(Object key) { if (this.counter == null) { this.counter = this.createCounter(); } this.counter.increment(); if (this.rule == null) { return null; } else { try { return this.rule.choose(key);//进行服务选择的Key } catch (Exception var3) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", new Object[]{this.name, key, var3}); return null; } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
🚕Ribbon负载均衡策略
跟进上面的rule,rule,规则,即负载均衡的规则,有以下几种
public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware { private static Logger logger = LoggerFactory.getLogger(BaseLoadBalancer.class); private static final IRule DEFAULT_RULE = new RoundRobinRule();//这里的rule默认值是一个`RoundRobinRule`的类型 private static final BaseLoadBalancer.SerialPingStrategy DEFAULT_PING_STRATEGY = new BaseLoadBalancer.SerialPingStrategy((SyntheticClass_1)null); private static final String DEFAULT_NAME = "default"; private static final String PREFIX = "LoadBalancer_"; protected IRule rule; protected IPingStrategy pingStrategy; protected IPing ping;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
RoundRobinRule(轮询策略):按照一定的顺序依次调用服务实例。多个服务轮流访问。它是Ribbon默认的负载均衡规则。
RandomRule(随机策略):从服务提供者的列表中随机选择一个服务实例。
WeightedResponseTimeRule(权重策略):根据每个服务提供者的响应时间分配⼀个权重,响应时间越长,权重越小,被选中的可能性也就越低。
RetryRule(重试策略):按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null。
AvailabilityFilteringRule(可⽤敏感性策略):先过滤掉⾮健康的服务实例,然后再选择连接数较⼩的服务实例。
ZoneAvoidanceRule(区域敏感策略):根据服务所在区域(zone)的性能和服务的可⽤性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。
BestAvailableRule(最小连接数策略):也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最⼩连接数,那么会调⽤轮询策略进行选取。即忽略那些短路的服务器,并选择并发数较低的服务器。
🚙自定义负载均衡策略
我们需要在order-service中的OrderApplication类中,定义一个新的IRule:
@Beanpublic IRule randomRule(){ return new RandomRule();}
- 1
- 2
- 3
- 4
配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
- 1
- 2
- 3
🚎Ribbon设置饥饿加载
Ribbon默认是采用懒加载,就是第一次访问的时候才会去创建LoadBalanceClient,这样的情况下会导致请求时间很长,影响我们的使用效率。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,以下是开启饥饿加载的配置
ribbon: eager-load: enabled: true clients: userservice
- 1
- 2
- 3
- 4
本文到此结束,希望能帮到各位小伙伴儿👏👏
如果文章有什么需要改进的地方还请大佬多多指教🤞🤞
以下是我的V信,欢迎加入我们的圈子🎉🎉
再次感谢各位大佬😘😘