Gateway自定义Instance选择器

想法

在使用gateway时gateway是这样处理请求的,当一个请求到达gateway时,gateway会从路由配置中选择一个Instance将这个请求转发过去(我们的服务都是通过lb://协议接入的),在默认情况下是随机选择Instance。所以有一个想法,能不能根据Instance的负载,选择负载最小的那个Instance进行转发。我们的服务接入了promethus或者actuator可以通过它们获取到一个衡量服务器负载的参数。

方案

首先确定一个参数来衡量Instance的负载,这里采用Prometheusprocess_cpu_usage这个参数,为了获取这个参数,需要每个Instance都加载promethus的插件。gateway通过访问promethus的接口获取到process_cpu_usage的数值,我们将相同Service的这个参数放在一个list中,然后做好排序,每次转发时选取负载最少的那个,将请求转发到这个Instance。这个list每10秒左右维护一次,重新获取下process_cpu_usage,并且排序。但这里有一个小问题,不能保证此时Instance还在正常工作中,所以,在转发之前先发送一个请求到Instance,看看是不是正常工作中,如果不工作了,那么按照顺序选取下一个Instance。如果promethus的接口出问题了,或者返回延迟了,那么就随机一个Instance转发。

方案总结

  • 建立一个Instance的list。这个list按照system.load.average.1m排序。
  • 建立一个定时任务维护这个list
  • 自定义一个LoadBalancerClientFilter类,用来替换默认的Filter,这个Filter按照list排序选择Instance转发请求

实现

  1. promethus的相关处理
@Data
public class InstanceData {
   
    private Boolean death;
    private ServiceInstance serviceInstance;
    private Map<String, PrometheusData> prometheusDatas;
}

@Data
public class PrometheusData {
   
    private Long timestamp;
    private String name;
    private String type;
    private String description;
    private List<MetricData> datas;

    public void addMetricData(MetricData data){
   
        if(datas==null)
            datas=new ArrayList<>();
        datas.add(data);
    }

    @Data
    public static class MetricData{
   
        private Float value;
        private Map<String,String> metric;
    }
}


private Map<String,List<InstanceData>> serviceDataMap=new ConcurrentHashMap<>();

private Map<String, Map<String,InstanceData>> instanceDataMap=new ConcurrentHashMap<>();

public List<InstanceData> getInstanceDataList(String servicdId){
   
        return serviceDataMap.get(servicdId);
    }

  • 定义一个全局变量instanceDataMap保存Instance的数据(按照Service分),
  • 定义一个全局变量serviceDataMap保存Service的数据,
  • 定义一个类InstanceData,将Instancepromethus的返回数据封装在一起
  • promethus的返回结构处理成PrometheusData,这样基本的数据结构定义完成。
  • 通过List<InstanceData> getInstanceDataList(String servicdId)函数获取Instance的List。这个List的第一个元素就是我们转发的Instance。

@Slf4j
public class PrometheusHandler implements Function<String, List<PrometheusData>> {
   
    @Override
    public List<PrometheusData> apply(String m) {
   
        String[] ms=m.split("[\n]");
        final String[] data=new String[2];
        List<PrometheusData> prometheusDatas=new ArrayList<>();
        PrometheusData prometheusData=null;
        for(String s:ms){
   
            if(s.startsWith("#")){
   
                String[] sarray=s.split("[ ]");
                if(sarray[1].equals("HELP")){
   
                    prometheusData=new PrometheusData();
                    prometheusData.setTimestamp(System.currentTimeMillis());
                    prometheusDatas.add(prometheusData);
                    prometheusData.setName(sarray[2]);
                    String description=s.replace("#","").replace("HELP","").replace(sarray[2],"").trim();
                    prometheusData.setDescription(description);
                    data[0]=sarray[2];
                }else 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值