基于redis实现阿里云oss对象上传的简易负载均衡器

在使用阿里云的oss存储时,我突然想到,如果同时有100个请求往oss的Bucket容器中存储文件,因为阿里云的每个容器有着同时上传次数的限制,为了避免因为这种情况导致效率的下降,所以我觉得在oss中定义一个主容器,多个子容器,来避免次数限制而无法快速上传文件的弊端(这里不讨论的money的消耗)。所以我想了一个低端,但是简单的方法,来让系统对容器进行自主选择,实现简易的负载均衡器。我使用aop的方式,在每次上传方法被调用时,执行系统的容器选择,不能够修改参数,最优选择的方式就是查看哪个容器接受的上传文件请求最少,就是用哪个容器。

꒰ᐢ⸝⸝•༝•⸝⸝ᐢ꒱ ​​ 一个大一学生的想法,轻点喷 !!(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )

public String loadBalancer(String bucketName){
        Map<String,Long> map =new HashMap<>();
        //获取所有的bucket
        try{
            List<Bucket> buckets = oss.listBuckets();
            //获取所有的bucket名称
            buckets.stream().map(
                    bucket -> {
                        Long size = redis.opsForList().size(bucketLoadName+":" + bucket.getName());
                        map.put(bucket.getName(),size);
                        return null;
                    }
            ).forEach(e->{});
            // 获取最小的容器名称
            Optional<Map.Entry<String,Long>> minEnity = map.entrySet().stream().min(Map.Entry.comparingByValue());
            if(minEnity.isPresent()){
                String key = minEnity.get().getKey();
                log.info("将{}容器负载均衡到{}容器",bucketName,key);
                //往redis中添加一个负载均衡计数器
                redis.opsForList().rightPush(bucketLoadName+":"+key,key);
               return key;
            }
        }catch (Exception e){
            log.error("查询出现异常,{}",e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
        return null;
    }
 /**
     * 除copyFile方法外的其他方法,都切面
     * */
    @Around("execution(* org.tamall.fileioservice.service.fileOptions.*(..)) &&" +
            " !execution(* org.tamall.fileioservice.service.fileOptions.copyFile(..))" +
            " && !execution(* org.tamall.fileioservice.service.fileOptions.deleteFile(..))")
    public Object pointCut(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature signature =(MethodSignature) proceedingJoinPoint.getSignature();
        //获取到切入的方法中的形参
        List<String> list = Arrays.asList(signature.getParameterNames());
        //获取到切入方法的实参
        Object[] args = proceedingJoinPoint.getArgs();
        List<Object> list1 = Arrays.asList(args);
        //获取指定个参数参数的索引
        int index = IntStream.range(0, list.size())
                .filter(i -> "bucketName".equals(list.get(i))).findFirst().orElse(-1);
        boolean b = queryExistence(CannedAccessControlList.PublicRead, (String) list1.get(index));
        if(!b){
            // 负载均衡后的新容器名
            String s = loadBalancer((String) list1.get(index));
            // 修改容器名称
            args[index] = s;
        }
        return proceedingJoinPoint.proceed(args);
    }

    /**
     * ordinaryUpdataFile方法,切面
     * 用于删除在redis中的负载均衡计数器
     * */
    @AfterReturning(pointcut = "execution(* org.tamall.fileioservice.service.fileOptions.ordinaryUpdataFile(..))", returning = "result")
    public void afterPointCut(JoinPoint proceedingJoinPoint, Object result) throws InterruptedException {

        MethodSignature signature =(MethodSignature) proceedingJoinPoint.getSignature();
        List<Class> list1 = Arrays.asList(signature.getParameterTypes());
        list1.stream().filter(i -> i.equals(MultipartFile.class)).map(e->{
            //获取到切入的方法中的形参
            List<String> list = Arrays.asList(signature.getParameterNames());
            //获取到切入方法的实参
            Object[] args = proceedingJoinPoint.getArgs();
            //获取指定个参数参数的索引
            int index = IntStream.range(0, list.size())
                    .filter(i -> "bucketName".equals(list.get(i))).findFirst().orElse(-1);
            // 删除redis计数器中存储的容器名,是容器名下的参数数量减一,必须是ordinaryUpdataFile携带MultipartFile参数的方法,用于区别普通上传和批量上传
            redis.opsForList().rightPop(bucketLoadName+":"+args[index]);
            return null;
        }).forEach(e->{});
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃着烧烤敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值