微服务系列--Ribbon负载均衡
1、前言
这篇文章接上一篇文章进行开发,上一篇整合完了Nacos,这篇来整合Ribbon。Ribbon不属于SpringCloud Alibaba的东西,而是基于Netflix Ribbon实现的。可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。
2、核心注解
Rabbin的依赖不需要进行重复导入,因为我们上一篇在导入nacos的时候,其实就已经导入进来了,nacos引入的相关依赖里面,包含了ribbon的jar包。
ribbon使用起来极其简单,用一个@LoadBalanced 注解就能实现基本的功能。在我们的RestTemplate Bean上增加注解,@LoadBalanced注解是属于Spring,而不是ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。
package com.chen.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConsumerConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3、配置负载均衡接口
在controller里面新增一个接口,接口指定实例名和provider的接口名
package com.chen.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/index")
public String index(){
List<ServiceInstance> provider = discoveryClient.getInstances("provider");
int index = ThreadLocalRandom.current().nextInt(provider.size());
String url = provider.get(index).getUri()+"/provider/index";
return this.restTemplate.getForObject(url, String.class);
}
@GetMapping("/index_ribbon")
public String index_ribbon(){
return "ribbon均衡调用:"+this.restTemplate.getForObject("http://provider/provider/index", String.class);
}
}
OK,自此,调一下接口测试一下,浏览器输入:localhost:8080/consumer/index_ribbon
发现就是这两个接口进行轮询调用
ribbon如果不指定规则的话,那么就是默认轮询规则,按顺序依次调用。
4、设置随机规则
spring:
cloud:
nacos:
discovery:
# 配置nacos服务地址,如果不配置,默认是localhost:8848
server-addr: localhost:8848
application:
name: consumer
server:
port: 8080
provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
我这里设置了com.netflix.loadbalancer.RandomRule随机规则,继续调接口测试可以发现,现在已经变成无规律的了。
5、设置权重规则
在nacos可视化界面,服务详情里面,可以看到每一个实例都可以单独设置权重
顾名思义,改变了这个权重值,那么在调接口的时候,就会根据这个权重去随机调取某个实例的接口,权重值越大, 调取接口的概率越大。但是,改完之后再进行测试可以发现,这个权重值没有生效,这还需要我们重写AbstractLoadBalancerRule类的choose方法进行实现,代码如下:
package com.chen.config;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
//读取配置文件
}
@Override
public Server choose(Object o) {
ILoadBalancer loadBalancer = this.getLoadBalancer();
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) loadBalancer;
//获取要请求的微服务名称
String name = baseLoadBalancer.getName();
//获取服务发现的相关API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("选择的实例是port={},instance={}",instance.getPort(),instance);
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
return null;
}
}
}
然后,在yml文件里面把规则指向我们继承的这个规则类
spring:
cloud:
nacos:
discovery:
# 配置nacos服务地址,如果不配置,默认是localhost:8848
server-addr: localhost:8848
application:
name: consumer
server:
port: 8080
provider:
ribbon:
NFLoadBalancerRuleClassName: com.chen.config.NacosWeightedRule
再次进行测试就会发现权重值已经生效。
还没有评论,来说两句吧...