微服务的服务间调用组件Ribbon以及OpenFeign

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的地址。

软件负载均衡和硬件负载均衡

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://eureka7001.com:7001/eureka/,http://eureka7002.com: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的配置一样(需要引入相关的配置类和注解)

猜你喜欢

转载自blog.csdn.net/rakish_wind/article/details/121445761