1、ribbon基本概念
ribbon是springcloud生态下netflix的一个服务组件,其作用用来做客户端负载均衡
在springcloud的官网中,我们还可以看到很多其他组件提供者,如springcloud alibaba
spring-cloud-netflix的ribbon是一种客户端负载的工具,和nginx在服务端负载相反。
可以结合feign(远程接口调用)使用,实现伪RPC,在客户端上使用@FeignClient注解,开启远程接口调用。
2、ribbon的使用
pom.xml引入依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> <version>2.2.3.RELEASE</version> </dependency>
这里我建了一个orderservice和userservice,通过userservice访问orderservice请求,使用RestTemplate
2.1、在没有加ribbon之前,访问orderservice
userservice:
@RestController @RequestMapping("user") public class UserController { @Autowired private RestTemplate restTemplate; @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } @GetMapping("/user/{userId}") public String getOrderByUser(@PathVariable("userId") Long userId){ return restTemplate.getForObject("http://localhost:8080/order/list",String.class); } }
orderservice:
@RestController @RequestMapping("order") public class OrderController { @GetMapping("/list") public String listOrders(){ System.out.println("——————被调用了——————"); return "list order " + LocalDateTime.now(); } }
测试结果:
list order 2020-07-13T21:30:34.480
这里的请求地址是写死的,如果我们访问的一个集群,根据需求来使用不同的策略来访问远程接口,实现负载功能,那么这样肯定就行不通。
所以ribbon就可以帮我们解决这个问题
2.2、加ribbon之后
修改代码:
1、配置文件yml或properties
这里是properties文件:
orderservice是我们需要访问的服务名
# 配置指定服务的提供者的地址列表 orderservice.ribbon.listOfServers= localhost:8080,localhost:8081,localhost:8082
2、在RestTemplate 实例加上@LoadBalanced注解
@LoadBalanced @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); }
3、将请求地址的固定localhost:8080换成orderservice(访问的服务名)
@GetMapping("/user/{userId}") public String getOrderByUser(@PathVariable("userId") Long userId){ return restTemplate.getForObject("http://orderservice/order/list",String.class); }
4、在访问的应用中设置服务名。
spring.application.name=orderservice
orderservice启动了三个服务,模拟集群,idea 同一个项目多个端口号启动
测试:当我们访问了几次后,根据打印结果,发现访问orderservice三个服务时都是按顺序访问,即8080-》8081-》8082
也也是ribbon默认采用轮询算法。除此之外,ribbon还支持很多的访问策略,也可以自定义策略:
IRule接口类图:
修改ribbon默认的策略:
修改userservice服务的properties或yml文件:
server.port=8088 # 配置指定服务的提供者的地址列表 orderservice.ribbon.listOfServers= localhost:8080,localhost:8081,localhost:8082 #配置访问策略,com.netflix.loadbalancer.RandomRule为策略的全类名 orderservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
测试:访问orderservice服务10次,8080调用了6次,8081调用了2次,8082调用了2次
3、自定义ribbon访问策略
除了ribbon已经提供的策略,我们也可以自定义策略,只需要继承AbstractLoadBalancerRule类
这里我们设定访问的服务一直是第二个,即8081端口
public class MyRule extends AbstractLoadBalancerRule { @Override public void initWithNiwsConfig(IClientConfig clientConfig) { } @Override public Server choose(Object key) { ILoadBalancer lb = getLoadBalancer(); if (lb == null) { return null; } Server server = null; while(server==null){ List<Server> serverList = lb.getAllServers(); int index = 1; server = serverList.get(index); } return server; } }
修改properties文件,指定访问策略:
server.port=8088 # 配置指定服务的提供者的地址列表 orderservice.ribbon.listOfServers= localhost:8080,localhost:8081,localhost:8082 #配置访问策略,com.atyoung.user.MyRule为策略的全类名 orderservice.ribbon.NFLoadBalancerRuleClassName=com.atyoung.user.MyRule
测试结果:访问orderservice10次:
我们8081端口访问了10次,其他端口没有访问:
4、ribbon的原理及源码解析
5、ribbon的整合
在上面案例我们可以看到在访问远程服务时,需要写一个RestTemplate,去实现请求,如果每个方法里面都这么写
将会是一件很麻烦的事,这时候feign就可以帮助我们去干这样的事,它可以以接口编程的形式发送请求,即伪rpc,可以实现dubbo那样的效果
除此之外,我们还可以注意到配置文件的问题,当我们需要新增一个服务是,我们需要关闭服务修改配置文件重新发布,当我们有的服务器出现故障
又无法动态的处理,所以我们需要一个可以服务动态上下线,并能够集中管理的地方,这时候我们就需要eureka了,它可以帮助我们搞定这些问题,
并提供dashboard来管理这些服务。