Spring Cloud Ribbon概述
目前主流的负载均衡方案
- 集中式负载均衡
- 进程内负载均衡
- 软件负载均衡和硬件负载均衡
- Ribbon的核心组件IRule
- Ribbon配置随机负载均衡
- 随机负载均衡底层核心代码
- Open Feign简介
- 配置和使用
- 依赖
- 启动类
- 封装接口
- 超时配置
- 日志增强级别
- 自定义负载均衡
Spring Cloud 系列笔记总目录:Spring Cloud 学习笔记
Spring Cloud Ribbon概述
- Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
- Spring Cloud Ribbon只是一个工具类框架,不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括Feign也是基于Ribbon实现的工具。
- 一句话:ribbon就是负载均衡+RestTemplate调用
- 现在Ribbon已经停止维护,但是还是有不少人使用
目前主流的负载均衡方案
集中式负载均衡
- 即在consumer和provider之间使用独立的负载均衡设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至provider
进程内负载均衡
- 将负载均衡逻辑集成到consumer,consumer从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的provider
Ribbon就属于后者,它只是一个类库,集成于consumer进程,consumer通过它来获取到provider的地址。
软件负载均衡和硬件负载均衡
- 浅谈软件和硬件负载均衡(LVS、HAProxy、Nginx、F5)及一次线上问题分析
Ribbon的核心组件IRule
- Ribbon默认的负载均衡算法是轮询(原理是取模服务总数),而IRule是根据特定的算法中从服务列表中选取其中一个要访问的服务。
Ribbon配置随机负载均衡
添加依赖,ribbon的依赖一般都集成在了starter里面
- 在启动类所在包的同级目录下创建一个包,然后新建一个类
@Configuration
public class MySelfRule
{
@Bean
public IRule myRule()
{
return new RandomRule();//定义为随机
}
}
- 启动类加一行注解: @RibbonClient(name = “CLOUD-PAYMENT-SERVICE”,configuration=MySelfRule.class)
- name是指被调用的服务名称
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration=MySelfRule.class)
public class OrderMain80
{
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
随机负载均衡底层核心代码
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);//获取server
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;
}
}
}
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {//cas自旋
current = this.nextServerCyclicCounter.get();
next = (current + 1) % modulo;
} while(!this.nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
Open Feign简介
- Feign是一个声明式WebService客户端。使用Feign能让编写WebService客户端更加简单。
- Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由社区进行维护,更名为 Openfeign
- 使用方法:定义一个服务接口然后在上面添加注解。Feign也能支持可拔插式的编码器和解码器。
- Spring Cloud对Feign进行了封装,使其能够支持SpringMVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用完成负载均衡。
- Feign旨在使Java Http客户端变得更加容易。在使用Ribbon+RestTemplate时,往往一个服务提供接口会被多处调用。所以,Feign在此基础上做了进一步的封装,由他来帮助我们定义和实现接口。在Feign的实现下,我们只需要使用注解配置接口,即可完成对服务提供方的接口绑定,简化了自己封装服务调用的工作量。
配置和使用
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
启动类
@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80
{
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class, args);
}
}
封装接口
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")//被调用的服务名
public interface PaymentFeignService
{
@GetMapping(value = "/payment/get/{id}")//被调用的接口地址
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
@GetMapping(value = "/payment/feign/timeout")
String paymentFeignTimeout();
}
超时配置
- feign请求服务接口默认只等待1s
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://:7001/eureka/,http://:7002/eureka/
#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
#指的是建立连接后从服务器读取到可用资源所用的时间
ReadTimeout: 5000
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ConnectTimeout: 5000
logging:
level:
# feign日志以什么级别监控哪个接口
com.atguigu.springcloud.service.PaymentFeignService: debug
日志增强级别
@Configuration
public class FeignConfig
{
@Bean
Logger.Level feignLoggerLevel()
{
return Logger.Level.FULL;//FULL是最详细的级别
}
}
自定义负载均衡
- 和ribbon的配置一样(需要引入相关的配置类和注解)