限流-------------令牌桶算法

令牌桶算法 一算法 令牌桶算法和漏桶算法不同的是,有时后端能够处理一定的突发情况,只是为了系统稳定,一般不会让请求超过正常情况的60%,给容灾留有余地。但漏桶算法中后端处理速度是固定的,对于短时的突发情况,后端不能及时处理,和实际处理能力不匹配。 令牌算法是以固定速度往一个桶内增加令牌,当桶内令牌满了后,就停止增加令牌。上游请求时,先从桶里拿一个令牌,后端只服务有令牌的请求,所以后端处理速度不一定是匀速的。当有突发请求过来时,如果令牌桶是满的,则会瞬间消耗桶中存量的令牌。如果令牌还不够,那么再等待发放令牌(固定速. 阅读详情

限流

限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。

在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流

  • 缓存:缓存的目的是提升系统访问速度和增大系统处理容量
  • 降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行
  • 限流:限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理

我们经常在调别人的接口的时候会发现有限制,比如微信公众平台接口、百度API Store、聚合API等等这样的,对方会限制每天最多调多少次或者每分钟最多调多少次

我们自己在开发系统的时候也需要考虑到这些,比如我们公司在上传商品的时候就做了限流,因为用户每一次上传商品,我们需要将商品数据同到到美团、饿了么、京东、百度、自营等第三方平台,这个工作量是巨大,频繁操作会拖慢系统,故做限流。

以上都是题外话,接下来我们重点看一下令牌桶算法

令牌桶算法

下面是从网上找的两张图来描述令牌桶算法:

   

RateLimiter

https://github.com/google/guava

RateLimiter的代码不长,注释加代码432行,看一下RateLimiter怎么用

复制代码

 1 package com.cjs.example;
 2 
 3 import com.google.common.util.concurrent.RateLimiter;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.RestController;
 6 
 7 import java.text.SimpleDateFormat;
 8 import java.util.Date;
 9 
10 @RestController
11 public class HelloController {
12 
13     private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
14 
15     private static final RateLimiter rateLimiter = RateLimiter.create(2);
16 
17     /**
18      * tryAcquire尝试获取permit,默认超时时间是0,意思是拿不到就立即返回false
19      */
20     @RequestMapping("/sayHello")
21     public String sayHello() {
22         if (rateLimiter.tryAcquire()) { //  一次拿1个
23             System.out.println(sdf.format(new Date()));
24             try {
25                 Thread.sleep(500);
26             } catch (InterruptedException e) {
27                 e.printStackTrace();
28             }
29         }else {
30             System.out.println("limit");
31         }
32         return "hello";
33     }
34 
35     /**
36      * acquire拿不到就等待,拿到为止
37      */
38     @RequestMapping("/sayHi")
39     public String sayHi() {
40         rateLimiter.acquire(5); //  一次拿5个
41         System.out.println(sdf.format(new Date()));
42         return "hi";
43     }
44 
45 }

复制代码

关于RateLimiter:

  • A rate limiter。每个acquire()方法如果必要的话会阻塞直到一个permit可用,然后消费它。获得permit以后不需要释放。
  • RateLimiter在并发环境下使用是安全的:它将限制所有线程调用的总速率。注意,它不保证公平调用。
  • RateLimiter在并发环境下使用是安全的:它将限制所有线程调用的总速率。注意,它不保证公平调用。Rate limiter(直译为:速度限制器)经常被用来限制一些物理或者逻辑资源的访问速率。这和java.util.concurrent.Semaphore正好形成对照。
  • 一个RateLimiter主要定义了发放permits的速率。如果没有额外的配置,permits将以固定的速度分配,单位是每秒多少permits。默认情况下,Permits将会被稳定的平缓的发放。
  • 可以配置一个RateLimiter有一个预热期,在此期间permits的发放速度每秒稳步增长直到到达稳定的速率

基本用法:

复制代码

final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
void submitTasks(List<Runnable> tasks, Executor executor) {
    for (Runnable task : tasks) {
        rateLimiter.acquire(); // may wait
        executor.execute(task);
    }
}

复制代码

实现

SmoothBursty以稳定的速度生成permit

SmoothWarmingUp是渐进式的生成,最终达到最大值趋于稳定

源码片段解读:

复制代码

public abstract class RateLimiter {

    /**
     * 用给定的吞吐量(“permits per second”)创建一个RateLimiter。
     * 通常是QPS
     */
    public static RateLimiter create(double permitsPerSecond) {
        return create(permitsPerSecond, SleepingStopwatch.createFromSystemTimer());
    }
    
    static RateLimiter create(double permitsPerSecond, SleepingStopwatch stopwatch) {
        RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */);
        rateLimiter.setRate(permitsPerSecond);
        return rateLimiter;
    }
    
    /**
     * 用给定的吞吐量(QPS)和一个预热期创建一个RateLimiter
     */
    public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
        checkArgument(warmupPeriod >= 0, "warmupPeriod must not be negative: %s", warmupPeriod);
        return create(permitsPerSecond, warmupPeriod, unit, 3.0, SleepingStopwatch.createFromSystemTimer());
    }

    static RateLimiter create(
            double permitsPerSecond,
            long warmupPeriod,
            TimeUnit unit,
            double coldFactor,
            SleepingStopwatch stopwatch) {
        RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit, coldFactor);
        rateLimiter.setRate(permitsPerSecond);
        return rateLimiter;
    }

    private final SleepingStopwatch stopwatch;

    //    锁
    private volatile Object mutexDoNotUseDirectly;

    private Object mutex() {
        Object mutex = mutexDoNotUseDirectly;
        if (mutex == null) {
            synchronized (this) {
                mutex = mutexDoNotUseDirectly;
                if (mutex == null) {
                    mutexDoNotUseDirectly = mutex = new Object();
                }
            }
        }
        return mutex;
    }
    
    /**
     * 从RateLimiter中获取一个permit,阻塞直到请求可以获得为止
     * @return 休眠的时间,单位是秒,如果没有被限制则是0.0
     */
    public double acquire() {
        return acquire(1);
    }
  
    /**
     * 从RateLimiter中获取指定数量的permits,阻塞直到请求可以获得为止
     */
    public double acquire(int permits) {
        long microsToWait = reserve(permits);
        stopwatch.sleepMicrosUninterruptibly(microsToWait);
        return 1.0 * microsToWait / SECONDS.toMicros(1L);
    }
    
    /**
     * 预定给定数量的permits以备将来使用
     * 直到这些预定数量的permits可以被消费则返回逝去的微秒数
     */
    final long reserve(int permits) {
        checkPermits(permits);
        synchronized (mutex()) {
            return reserveAndGetWaitLength(permits, stopwatch.readMicros());
        }
    }
    
    private static void checkPermits(int permits) {
        checkArgument(permits > 0, "Requested permits (%s) must be positive", permits);
    }
    
    final long reserveAndGetWaitLength(int permits, long nowMicros) {
        long momentAvailable = reserveEarliestAvailable(permits, nowMicros);
        return max(momentAvailable - nowMicros, 0);
    }
}


abstract class SmoothRateLimiter extends RateLimiter {
    
    /** The currently stored permits. */
    double storedPermits;

    /** The maximum number of stored permits. */
    double maxPermits;

    /**
     * The interval between two unit requests, at our stable rate. E.g., a stable rate of 5 permits
     * per second has a stable interval of 200ms.
     */
    double stableIntervalMicros;
    
    /**
     * The time when the next request (no matter its size) will be granted. After granting a request,
     * this is pushed further in the future. Large requests push this further than small requests.
     */
    private long nextFreeTicketMicros = 0L; // could be either in the past or future
    
    final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
        resync(nowMicros);
        long returnValue = nextFreeTicketMicros;
        double storedPermitsToSpend = min(requiredPermits, this.storedPermits);    //    本次可以获取到的permit数量
        double freshPermits = requiredPermits - storedPermitsToSpend;    //    差值,如果存储的permit大于本次需要的permit数量则此处是0,否则是一个正数
        long waitMicros =
            storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
                + (long) (freshPermits * stableIntervalMicros);    //    计算需要等待的时间(微秒)

        this.nextFreeTicketMicros = LongMath.saturatedAdd(nextFreeTicketMicros, waitMicros);
        this.storedPermits -= storedPermitsToSpend;    //    减去本次消费的permit数
        return returnValue;
    }
    
    void resync(long nowMicros) {
        // if nextFreeTicket is in the past, resync to now
        if (nowMicros > nextFreeTicketMicros) {    //    表示当前可以获得permit
            double newPermits = (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros();    //    计算这段时间可以生成多少个permit
            storedPermits = min(maxPermits, storedPermits + newPermits);    //    如果超过maxPermit,则取maxPermit,否则取存储的permit+新生成的permit
            nextFreeTicketMicros = nowMicros;    //    设置下一次可以获得permit的时间点为当前时间
        }
    }
}

复制代码

RateLimiter实现的令牌桶算法,不仅可以应对正常流量的限速,而且可以处理突发暴增的请求,实现平滑限流。

通过代码,我们可以看到它可以预消费,怎么讲呢

nextFreeTicketMicros表示下一次请求获得permits的最早时间。每次授权一个请求以后,这个值会向后推移(PS:想象一下时间轴)即向未来推移。因此,大的请求会比小的请求推得更。这里的大小指的是获取permit的数量。这个应该很好理解,因为上一次请求获取的permit数越多,那么下一次再获取授权时更待的时候会更长,反之,如果上一次获取的少,那么时间向后推移的就少,下一次获得许可的时间更短。可见,都是有代价的。正所谓:要浪漫就要付出代价。

还要注意到一点,就是获取令牌和处理请求是两个动作,而且,并不是每一次都获取一个,也不要想当然的认为一个请求获取一个permit(或者叫令牌),可以再看看前面那幅图

Stopwatch

一个以纳秒为单位度量流逝时间的对象。它是一个相对时间,而不是绝对时间。

Stopwatch stopwatch = Stopwatch.createStarted();
System.out.println("hahah");
stopwatch.stop();
Duration duration = stopwatch.elapsed();
System.out.println(stopwatch);

Semaphore(信号量)

A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly. 

一个信号量维护了一系列permits。

每次调用acquire()方法获取permit,如果必要的话会阻塞直到有一个permit可用为止。

调用release()方法则会释放自己持有的permit,即用完了再还回去。

信号量限制的是并发访问临界资源的线程数。

令牌桶算法 VS 漏桶算法

漏桶

漏桶的出水速度是恒定的,那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。

令牌桶

生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,而且拿令牌的过程并不是消耗很大的事情。

最后,不论是对于令牌桶拿不到令牌被拒绝,还是漏桶的水满了溢出,都是为了保证大部分流量的正常使用,而牺牲掉了少部分流量,这是合理的,如果因为极少部分流量需要保证的话,那么就可能导致系统达到极限而挂掉,得不偿失。

小定律:排队理论

https://en.wikipedia.org/wiki/Little%27s_law

the long-term average number L of customers in a stationary system is equal to the long-term average effective arrival rate λ multiplied by the average time W that a customer spends in the system. Expressed algebraically the law is:

在一个固定系统中,顾客的长期平均数量L等于顾客的长期平均到达速率λ乘以顾客在系统中平均花费的时间W。用公式表示为:

虽然这看起来很容易,但这是一个非常显著的举世瞩目的结果,因为这种关系“不受到达过程的分布,服务分布,服务顺序,或其他任何因素的影响”。这个结果适用于任何系统,特别是适用于系统内的系统。唯一的要求是系统必须是稳定的非抢占式的。

例子

例1:找响应时间

假设有一个应用程序没有简单的方法来度量响应时间。如果系统的平均数量和吞吐量是已知的,那么平均响应时间就是:

mean response time = mean number in system / mean throughput

平均响应时间 = 系统的平均数量 / 平均吞吐量.

 

例2:顾客在店里

想象一下,一家小商店只有一个柜台和一个可供浏览的区域,每次只能有一个人在柜台,并且没有人不买东西就离开。

所以这个系统大致是:进入 --> 浏览 --> 柜台结账 --> 离开

在一个稳定的系统中,人们进入商店的速度就是他们到达商店的速度(我们叫做到达速度),它们离开的速度叫做离开速度。

相比之下,到达速度超过离开速度代表是一个不稳定的系统,这就会造成等待的顾客数量将逐渐增加到无穷大。

前面的小定律告诉我们,商店的平均顾客数量L等于有效的到达速度λ乘以顾客在商店的平均停留时间W。用公式表示为:

假设,顾客以每小时10个的速度到达,并且平均停留时间是0.5小时。那么这就意味着,任意时间商店的平均顾客数量是5

现在假设商店正在考虑做更多的广告,把到达率提高到每小时20。商店必须准备好容纳平均10人,或者必须将每个顾客在商店中的时间减少到0.25小时。商店可以通过更快地结帐或者增加更多的柜台来达到后者的目的。

我们可以把前面的小定律应用到商店系统中。例如,考虑柜台和在柜台前排的队。假设平均有2个人在柜台前排队,我们知道顾客到达速度是每小时10,所以顾客平均必须停留时间为0.2小时。

最后

这是单机(单进程)的限流,是JVM级别的的限流,所有的令牌生成都是在内存中,在分布式环境下不能直接这么用。

如果我们能把permit放到Redis中就可以在分布式环境中用了。

参考

https://blog.youkuaiyun.com/jek123456/article/details/77152571

https://blog.youkuaiyun.com/syc001/article/details/72841951

https://segmentfault.com/a/1190000012875897

https://blog.youkuaiyun.com/charleslei/article/details/53152883

https://www.jianshu.com/p/8f548e469bbe

https://www.cnblogs.com/f-zhao/p/7210158.html

https://m.jb51.net/article/127996.htm

算法:限流之令牌桶算法实现 本章介绍令牌桶Token Bucket算法在流量限速场景的原理,以及C++实现和相关测试验证。常见的限流算法有计数限流,固定窗口限流,滑动窗口限流,漏桶算法限流和令牌桶算法限流。令牌桶算法是限流算法的一种,其原理是系统会以一个恒定的速度往桶里放入固定数量的令牌,而如果请求需要被处理,则需要先从桶里获取对应令牌,当桶里没有令牌可取时,则拒绝服务。令牌桶算法可应用于多种场景,本章是针对网络流控制限制场景的使用,对外发的网络数据进行控制,使数据以长期的平均速率外发,并运行一个瞬时的最高流量。 阅读详情

相关推荐

什么是限流?为什么会限流呢?常见的限流算法【固定窗口限流、滑动窗口限流、漏桶限流、令牌桶限流】是什么呢?

限流是指在系统面临高并发、大流量请求的情况下,限制新的流量对系统的访问,从而保证系统服务的安全性。另一种解释:在计算机网络中,限流就是控制网络接口发送或接收请求的速率,它可防止DoS攻击和限制Web爬虫。固定窗口限流算法(Fixed Window Rate Limiting Algorithm)是一种最简单的限流算法,其原理是在固定时间窗口(单位时间)内限制请求的数量。该算法将时间分成固定的窗口,并在每个窗口内限制请求的数量。

一个写湿的程序猿 6954

令牌桶算法限流

限流 限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流 缓存:缓存的目的是提升系统访问速度和增大系统处理容量 降级:降级是当服务器压力剧增的情况下,根据...

weixin_33819479的博客 883

令牌桶算法实现限流

试想这样的场景, 尽管服务器的 QPS 已经达到限速阈值了, 但是并不想将所有的流量都拒之门外, 仍然让部分流量能够正常通过限流器. 这样我们的服务器在面对突发流量时能够有一定的伸缩空间, 而不是一直处于不可用状态。 在开发高并发的系统时,有很多手段来保护系统,如缓存、降级和限流等。缓存可以提升系统的访问速度,降级可以暂时屏蔽掉非核心业务,使得核心业务不受影响。限流的目的通过对并发访问进行限速,一旦达到一定的速率就可以拒绝服务(定向到错误页或告知资源没有了)、排队等待(如秒杀、评论、下单等)、降级(直接返回

big_white_py的博客 5195

RateLimiter限流

网络应用限流场景,可以使用RateLimiter实现。 https://google.github.io/guava/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html

ligeforrent的专栏 427

限流之漏桶算法和令牌桶算法实现区别

问题描述? 某天A君突然发现自己的接口请求量突然涨到之前的10倍,没多久该接口几乎不可使用,并引发连锁反应导致整个系统崩溃。如何应对这种情况呢?生活给了我们答案:比如老式电闸都安装了保险丝,一旦有人使用超大功率的设备,保险丝就会烧断以保护各个电器不被强电流给烧坏。同理我们的接口也需要安装上“保险丝”,以防止非预期的请求对系统压力过大而引起的系统瘫痪,当流量过大时,可以采取拒绝或者引流等机制。1、漏...

感冒石头的博客 1685

令牌桶限流算法原理与源代码实现(Java、Golang)

令牌桶(Token Bucket)算法是一种常用的网络流量控制算法,用于限制请求的平均速率,同时允许一定程度的突发流量。令牌桶算法的优势在于它既能控制请求的平均速率,又能应对突发流量,这种灵活性使其成为现代系统限流的首选方案。下面提供几种 Golang 实现令牌桶限流算法的方式,从基础版本到并发安全版本,最后是分布式实现思路。这个实现涵盖了令牌桶算法的核心特性,并提供了线程安全和分布式扩展的能力,适用于大多数限流场景。下面提供一个完整的令牌桶限流算法的 Java 实现,包含了基础实现和线程安全版本。

AI天才研究院 873

限流——漏桶算法和令牌桶算法的区别

限流 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流 缓存:缓存的目的是提升系统访问速度和增大系统处理能力 降级:当服务流量剧增,影响到核心流程的性能,需要暂时屏蔽掉一些功能,待高峰过去或问题解决后再重新打开,以此释放服务器资源以保证核心任务的正常运行。 限流:限流的目的是通过对并发访问或请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、或排队或等待、降级等处理 常用的限流算法有令牌桶和,漏桶,滑动窗口 漏桶算法 漏桶(Leaky Bucket) 算

Emine 1万+

RateLimiter:C#速率限制实用程序

RateLimiter C#客户端速率限制实用程序。 动机 最初的动机是创建帮助程序,以遵守客户端应用程序中的Web服务速率限制。 但是,在需要临时限制一个共享资源使用情况的其他情况下,该帮助程序也可以使用。 产品特点 易于使用 完全异步:资源使用率低于线程睡眠 可通过CancellationToken取消 线程安全,因此您可以共享时间限制对象以使用同一资源对不同线程进行速率限制 可组合:在一个约束中组合不同速率限制的能力 安装 Install-Package RateLimiter -Version 2.2.0 样品用法 基本的 RateLimiters可以等待:等待之后执行的代码将遵守时

高并发系统限流-漏桶算法和令牌桶算法

参考: http://www.cnblogs.com/LBSer/p/4083131.html https://blog.youkuaiyun.com/scorpio3k/article/details/53103239 https://www.cnblogs.com/clds/p/5850070.html http://jinnianshilongnian.iteye.com/blog/2305117 ht...

weixin_42296449的博客 8293

RateLimiters:.NET中的令牌桶和泄漏令牌桶实现

RateLimiters .NET中的和实现。 这些策略可用于对各种Web,后端或API调用方案中的限制请求进行评分。 此项目是@sudohippie在此之后的.NET克隆。 建置状态 该库使用服务不断集成。

QT下利用FFTW实现功率谱密度分析(周期图法)

写在前面 出于项目需求,需要在QT的msvc 2015编译环境下实现功率谱密度估计。 所以这个需求很直接的关键词就是 1. C++ 2. QT 3. 傅里叶变换 4. 功率谱密度估计 但是在网上搜索了很久,没有一个非常直接的答案。所以我觉得很有必要写一篇文章来说明,在QT msvc2015 32bit环境下如何实现功率谱密度估计。 本文并没有经过严格编辑,但代码是已经可以跑通的,如...

李时珍食疗志的博客 5223

接口限流算法之漏桶算法&令牌桶算法

知识的广度来自知识的深度,学习如果不成体系那是多可怕的一件事儿,希望我们在未来的学习道路上坚守初心,不要给自己留下遗憾,以自己喜欢的方式生活,做自己喜欢做的事,宠爱自己,做一个独一无二的自己! 对于文章中出现的任何错误请大家批评指出,会及时做出修改! 有任何想要讨论和学习的问题可联系我:cittaksana@qq.com 接口限流算法之漏桶算法&令牌桶算法限流算法漏桶算法令牌桶算法RateLimiter 用法预消费能力令牌桶算法VS漏桶算法 工作中对外提供的API 接口设计都要考虑限流,如果.

Archie_Could的博客 4861

基于STM32与FPGA Cyclone IV的FSMC高速数据通信实战解析

本文详细解析了基于STM32的FSMC接口与FPGA Cyclone IV实现高速并行数据通信的实战方案。通过将FPGA模拟为SRAM设备,构建了MCU与FPGA之间的高速数据通道,并深入探讨了硬件连接、STM32软件配置、FPGA逻辑设计及性能优化等关键步骤,为图像处理、高速采集等需要大数据量交换的嵌入式应用提供了稳定高效的通信解决方案。

swift5iosmith的博客 295

令牌桶算法和漏桶算法限流

令牌桶和漏桶算法是两种常用的流量控制方法。令牌桶以固定速率生成令牌,允许突发流量消费桶内令牌,适用于API限流等场景。漏桶则以固定速率处理请求,严格控制输出速率,适合网络带宽管理等场景。两者核心区别在于:令牌桶允许短期突发而漏桶强制平滑输出。实际应用中令牌桶更常用(如Guava的RateLimiter),因其在控制长期速率的同时能兼容业务突发需求。

27届Java后端炒粉练习生,AICoding中........ 1055

从零开始学习信号完整性(SIPI)--1 简介

信号完整性就是研究如何让驱动芯片发出的信号经过传输通道被接收芯片正确接收的学问。 信号完整性包含了三个要素: 信号:是被传输的主体,我们首先要了解、熟悉信号的特性。 芯片:分为驱动芯片和接收芯片,信号完整性工程师就是要实现信号在驱动芯片和接收芯片之间的正确传输。 传输通道:是传输信号的介质,是信号所走的“路”。如何实现信号的正确传输呢?那就要信号完整性工程师为信号“修路”、“搭桥”。

qq_29476769的博客 4万+

TCGA数据集介绍及数据下载指南(新手友好篇)

目录一、TCGA数据集介绍1.1 数据集介绍1.2 File介绍1.2.1 Data Category(数据类别)1.2.2 Data Type(数据类型)1.2.3 Experimental Strategy(实验策略)1.2.4 Workflow Type(工作流类型)1.2.5 Data Format(数据格式)1.2.6 Platform(平台)1.2.7 Access1.3 Cases介绍1.3.1 Case ID(案例编号)1.3.2 Primary Site(主要站点)1.3.3 Progra

Wendy的博客 6万+

【 限流技术 | 从四大限流算法到Redisson令牌桶实践 】

本文介绍限流技术,解析固定窗口、滑动窗口、漏桶、令牌桶四种算法的原理、实现及优缺点,其中令牌桶因支持突发流量更推荐。还结合 Redisson 与 AOP 实现分布式令牌桶限流,通过注解配置多维度规则,解耦业务与限流逻辑。

2025优快云博客之星Top246,后端开发技术领域新星创作者。 1627

从零到一:STM32CubeMX虚拟串口开发中的常见陷阱与优化策略

本文深入探讨了STM32CubeMX在USB虚拟串口开发中的常见问题与优化策略,涵盖数据流吞吐量瓶颈、实时性约束等核心挑战。通过实战案例和代码示例,详细解析了波特率同步异常、数据丢失等问题的解决方案,并提供了DMA配置和中断优先级调优的高级技巧,帮助开发者提升STM32虚拟串口的性能和可靠性。

weixin_29164185的博客 370

手写RPC-令牌桶限流算法实现,以及常见限流算法

分布式架构下,不同服务之间频繁调用,对于某个具体的服务而言,可能会面临高并发场景。在这样的情况下,提供服务的每个服务节点就都可能由于访问量过大而引起一系列问题,比如我们再次借助 RPC框架来分析,RPC调用包括服务端和调用端。对于服务端来讲一般实现限流、降级算法;对于调用方来说一般实现熔断算法。加入服务调用方调用某个多服务节点的其中一个实现如下:此时对于特定的服务节点来说,可能存在多个不同调用者的调用,从而使得节点接收服务量超过其最大承载力。

one2excellent的博客 1755

告别Vivado自带编辑器!手把手教你用Sublime Text 4 + Icarus Verilog搭建FPGA开发环境(Windows 10/11)

本文详细介绍如何在Windows 10/11系统下,使用Sublime Text 4和Icarus Verilog搭建高效的FPGA开发环境,替代Vivado自带编辑器。通过配置语法检查、代码高亮和智能补全等功能,提升Verilog开发效率,实现专业级工作流。

weixin_30684743的博客 428

YOLO项目部署:从Python脚本到Docker容器的企业级交付全流程

YOLO模型企业级Docker部署方案 核心挑战 环境一致性:解决"本地能跑,服务器崩掉"问题 可扩展性:支持单实例到多实例扩展 稳定性:确保99.9%可用性 部署流程 项目改造:模块化代码,分离配置 Docker镜像:支持CPU/GPU环境 API服务:封装推理逻辑 监控告警:实现自动化运维 技术方案 需求 解决方案 环境一致性 Docker镜像+依赖冻结 可扩展性 K8s+负载均衡 稳定性 健康检查+自动重启 项目结构 模块化代码组织 外部化配置管理 精确依赖版本控制 摘要重点:通过

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1231

限流——令牌桶算法

限流——令牌桶算法 令牌桶简单来说就是有一个桶,然后假设里面存放了1000个令牌,我们访问一个接口需要有一个令牌,然后令牌桶中就会减少1个令牌,所以最多只能有1000个请求拿到令牌,但是,我们一般不会只有1000个令牌,所以,我们还需要设置每隔一段时间就会自动生成令牌 然后我们使用lua+redis来进行令牌桶限流代码的编写 这里使用的是springboot,先上代码 TokenBucket.class @Slf4j public class TokenBucket { //当前令牌桶的key

qq_45966902的博客 1986

AgentScope Java 2.0 项目实战:教你完整搭建企业级多租户AI数据分析Agent平台

本文详细讲解如何从零开始构建一个企业级多租户AI数据分析Agent平台(agentscope-dataagent)。涵盖项目的环境准备、项目骨架搭建、后端15个核心模块开发(认证授权、Agent网关、会话管理、SSE流式聊天、能力市场、Webhook通道、Docker沙箱等)、前端完整开发(路由守卫、SSE流式读取、28个页面组件)、内置资源定义、构建打包、测试验证及单机/Docker/分布式部署全流程。

program哲学 601
上一篇: Java集合类:LinkedHashMap
下一篇: ThreadLocal原理
U & Me
博客等级 码龄9年 3粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值