【高性能网关soul学习】13. 插件之springcloud

本文详细介绍了SpringCloudPlugin的工作原理,重点解析了如何利用SpringCloud的Ribbon实现客户端负载均衡。通过获取服务实例并重建请求URI,SpringCloudPlugin选择目标服务器执行请求。文中还展示了RibbonLoadBalancerClient的choose方法,该方法根据特定的负载均衡策略选择服务器,并通过轮询算法挑选合适的实例。
摘要由CSDN通过智能技术生成

【高性能网关soul学习】13. 插件之springcloud

本文目标:

  1. 介绍springcloud插件原理

SpringCloud 插件

springCloud 插件作为插件链的一环,处理springCloud 的请求

  1. 首先我们照惯例启动 soul-admin、soul-bootstrap(注意引入springcloud依赖 ),
  2. 然后启动 springCloud 的测试服务,使用了nacos 作为注册中心,配置如下

server:
  port: 8884
  address: 0.0.0.0
  
spring:
  application:
    name: springCloud-test
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

springCloud-test:
  ribbon.NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
# 指定了使用的负载均衡规则  
  
soul:
  springcloud:
    admin-url: http://localhost:9095
    context-path: /springcloud

下面我们直接分析 SpringCLoudPlugin做了哪些事情,主要就是使用客户端负载均衡 选择了一个目标请求服务器,然后将参数设置进 exchange 中


@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
    // ... 获取对象
  // 使用客户端负载均衡策略挑选一个合格的请求服务器
    final ServiceInstance serviceInstance = loadBalancer.choose(selectorHandle.getServiceId());
    if (Objects.isNull(serviceInstance)) {
        // ... 异常处理
    }
    // 重新构建请求 uri
    final URI uri = loadBalancer.reconstructURI(serviceInstance, URI.create(soulContext.getRealUrl()));
  
    String realURL = buildRealURL(uri.toASCIIString(), soulContext.getHttpMethod(), exchange.getRequest().getURI().getQuery());

    exchange.getAttributes().put(Constants.HTTP_URL, realURL);
    //set time out.
    exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
    return chain.execute(exchange);
}
  • loadBalancer 实际上为 RibbonLoadBalancerClient的实例对象,属于 LoadBalancerClient 客户端负载均衡的一种实现类
    • Ribbon是一个基于HTTP和TCP的客户端负载均衡器,当我们将Ribbon和注册中心一起使用时,Ribbon会从注册中心去获取服务端列表,然后进行轮询访问以到达负载均衡的作用,客户端负载均衡中也需要心跳机制去维护服务端清单的有效性,当然这个过程需要配合服务注册中心一起完成。
// RibbonLoadBalancerClient.java
public ServiceInstance choose(String serviceId, Object hint) {
    Server server = getServer(getLoadBalancer(serviceId), hint);
    if (server == null) {
        return null;
    }
    return new RibbonServer(serviceId, server, isSecure(server, serviceId),
            serverIntrospector(serviceId).getMetadata(server));
}

protected ILoadBalancer getLoadBalancer(String serviceId) {
    return this.clientFactory.getLoadBalancer(serviceId);
}

protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
    if (loadBalancer == null) {
        return null;
    }
    // Use 'default' on a null hint, or just pass it on?
  // 通过调用次数来轮询选择
    return loadBalancer.chooseServer(hint != null ? hint : "default");
}

Server chooseServer(Object key) {
  // 交由具体实例化的规则来挑选服务器
  return rule.choose(key);
}

public Server choose(Object key) {
    ILoadBalancer lb = getLoadBalancer();
  // lb从注册中心获取到所有的服务器,然后挑选出一个合格的服务器进行返回
    Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
    if (server.isPresent()) {
        return server.get();
    } else {
        return null;
    }       
}

// 对服务器进行过滤之后,然后
public Optional<Server> chooseRoundRobinAfterFiltering(List<Server> servers, Object loadBalancerKey) {
    List<Server> eligible = getEligibleServers(servers, loadBalancerKey);
    if (eligible.size() == 0) {
        return Optional.absent();
    }
  // 进行轮询计数和返回一个 Server
    return Optional.of(eligible.get(incrementAndGetModulo(eligible.size())));
}
  • IRule有非常多的实现类用来实现客户端的负载均衡策略(这里不再详述)
    规则
总结
  • SpringCloudPlugin 主要集成了 Spring cloud 自带的客户端负载均衡来挑选一个请求的目标服务器,因此 springCloudPlugin.doExecute() 方法自身实现的逻辑比较简单。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值