Ribbon简介与基本使用
一、Ribbon 简介
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。
- 硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;
- 软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。
Ribbon 通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。
二、Ribbon 可以做什么
Ribbon 的核心功能就是——LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用
常见的负载均衡软件:Nginx、Lvs等等
dubbo、SpringCloud中都给我们提供了负载均衡,其中,SpringCloud的负载均衡算法可以自定义。
负载均衡简单分类:
-
集中式LB:在服务的消费方和提供方之间使用独立的LB设施,如Nginx,由该设施负责把访问请求通过某种策略转发至服务的提供方。
- 例如:Nginx
-
进程式LB:将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后从这些地址中找到一个合适的服务器。
- 例如:Ribbon
Ribbon内部已有的一些负载均衡算法:随机、轮询(默认)、权重等等
三、Ribbon 简单使用
1、搭建环境:多个服务提供者、与之对应的多个数据库、Eureka Server集群。(之前的博客有)
接下来是在客户端,即服务消费方操作:
2、导入pom依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
3、在application.yaml中进行相关配置:
eureka:
client:
service-url:
defaultZone: http://eureka7001.com/eureka/,http://eureka7002.com/eureka/,http://eureka7003.com/eureka/
register-with-eureka: false
4、在 RestTemplate 配置文件中添加注解@LoadBalanced
package com.xingyu.springcloud.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 ConfigBean {
@Bean
@LoadBalanced //Ribbon负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
5、修改 Controller
之前的Controller如下:
package com.xingyu.springcloud.controller;
import com.xingyu.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
@Autowired
private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法,简单的restful服务模板
private static final String REST_URL_PREFIX = "http://localhost:8001";
@RequestMapping(value = "/consumer/dept/add", method = RequestMethod.POST)
public Boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept, Boolean.class);
}
@RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
public Dept getOne(@PathVariable Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
}
@RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
public List<Dept> getAll() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
}
其中:private static final String REST_URL_PREFIX = "http://localhost:8001";
这个语句设置了一个常量REST_URL_PREFIX用于指定服务的RESTurl地址,这样会固定只能访问8001,所以需要更改。将其中的localhost:8001
修改为Eureka Server页面(http://localhost:7001/)中服务实例的Application名:
所以将其修改成:private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
修改后的Controller:
package com.xingyu.springcloud.controller;
import com.xingyu.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
@Autowired
private RestTemplate restTemplate; //=提供多种便捷访问远程http服务的方法,简单的restful服务模板
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
@RequestMapping(value = "/consumer/dept/add", method = RequestMethod.POST)
public Boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept, Boolean.class);
}
@RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
public Dept getOne(@PathVariable Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
}
@RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
public List<Dept> getAll() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
}
结论:Ribbon和Eureka整合后,客户端可以直接调用服务,不需要关心IP地址和端口号。