java分布式应用限流实现

5 篇文章 0 订阅
4 篇文章 0 订阅

java分布式应用限流实现

题记

众所周知,现今分布式限流工具有许多,对于不同应用框架的支持也不尽相同,选择适合当前项目架构的限流技术才是最合适的。

分布式

什么是分布式

分布式系统(distributed system)是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。

分布式系统优点

提高系统并发量和吞吐率,通俗点讲,就是单台机器与多台机器同时工作的区别。

分布式核心问题

并发导致的系统问题,著名的CAP理论就是对分布式系统问题的诠释:一致性、可用性、分区容错性

数据一致性解决方案

最简单,最常见的方法就是实现分布式锁,如:采用数据库实现,采用Zookeeper实现,采用Redis实现等。

以上归纳的方法属于分布式并发问题的解决方案,本文主要对高并发场景的限流进行优化解决

限流

java并发限流
Java并发工具类(四)Semaphore
Java并发工具类(三)Exchanger
Java并发工具类(二)CyclicBarrier
Java并发工具类(一)CountDownLatch

java限流针对的是单机场景下对于接口执行的限制,可以满足指定的场景。但是用于分布式架构的系统中不合时宜。

分布式应用限流

实现分布式限流的思路有很多种

基于Redis的限流
Redissetnx的操作

固定时间窗口大小,不会有滑动窗口的效果,除非按照N:N,即为N个单位时间对应Nkey,动态实现计数。

Redis的数据结构zset
 public boolean limitZset(){

        int currentTime = Helper.getCurrentTime();

        int intervalTime = 10 * 1000;

        System.err.println("开始时间:" + currentTime);

        if(redisTemplate.hasKey("limit_key")) {

            Integer count = redisTemplate.opsForZSet().rangeByScore("limit_key", currentTime -  intervalTime, currentTime).size();        // intervalTime是限流的时间

            System.out.println(count);

            if (count != null && count > 5) {

                return false;

            }

        }

        redisTemplate.opsForZSet().add("limit_key",UUID.randomUUID().toString(),currentTime);

        System.err.println("结束时间:" + Helper.getCurrentTime());
        return true;

    }
Redis的令牌桶算法
public boolean limitLeakyBuckets (){

 Object result = redisTemplate.opsForList().leftPop("limit_leaky_buckets");
        if(result == null){
            return false;
        }
       return true;
    }


@Scheduled(fixedDelay = 10000,initialDelay = 0)
public void setToken(){

    redisTemplate.opsForList().rightPush("limit_leaky_buckets",UUID.randomUUID().toString());

    }
}
基于Hystrix的限流

Netflix公司在分布式微服务架构的践行下,将其保护服务的稳定性而设计的客户端熔断和断路器的解决方案,称之为Hystrix

Future限流实现

public class FutureDemo {

    private static final Random random = new Random();

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(()->{
            int nextInt = random.nextInt(200);
            System.out.printf("Thread : %s,睡眠时间: %s ms \n", Thread.currentThread().getName(),nextInt);
            try {
                Thread.sleep(nextInt);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                executorService.shutdown();
            }
            return "hello world";
        });

        try {
            future.get(100, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            System.out.println("服务熔断保护");
            e.printStackTrace();
        }
    }
}

Hystrix实现

@RestController
public class HelloWorldController {

    private final Random random = new Random();

    @GetMapping("/hello")
    @HystrixCommand(fallbackMethod = "errorOfHello",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")
            }
    )
    public String hello() throws InterruptedException {
        int nextInt = random.nextInt(200);
        System.out.printf("Thread : %s,睡眠时间: %s ms \n", Thread.currentThread().getName(), nextInt);
        Thread.sleep(nextInt);
        return "hello world";
    }

    @GetMapping("/hello2")
    public String hello2() throws InterruptedException {
        return new HystrixCommendDemo().execute();
    }


    public String errorOfHello() {
        return "error of hello world";
    }
}
基于Sentinel的限流

Sentinel是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

public static void main(String[] args) {
        initFlowRules(); //初始化规则
        while(true){
            Entry entry=null;
            try{
                entry= SphU.entry(resource); //准入判断
                System.out.println("Hello Word");
            }catch (BlockException e){//异常处理
                e.printStackTrace();
            }finally {
                if(entry!=null){
                    entry.exit();// 资源释放
                }
            }
        }
    }
Sentinel对比 Hystrix
对比内容SentinelHystrix
隔离策略信号量隔离线程池隔离/信号量隔离
熔断降级策略基于响应时间或失败比率基于失败比率
实时指标实现滑动窗口滑动窗口(基于 RxJava)
规则配置支持多种数据源支持多种数据源
扩展性多个扩展点插件的形式
基于注解的支持支持支持
限流基于 QPS,支持基于调用关系的限流不支持
流量整形支持慢启动、匀速器模式不支持
系统负载保护支持不支持
控制台开箱即用,可配置规则、查看秒级监控、机器发现等不完善
常见框架的适配Servlet、Spring Cloud、Dubbo、gRPC 等Servlet、Spring Cloud Netflix
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值