Больше отличных статей.
«Микросервисы — это не все, а лишь подмножество определенного домена».
С таким количеством компонентов мониторинга всегда найдется подходящий для вас
«С Нетти, что мы разрабатываем? 》
«Вероятно, это наиболее подходящая спецификация Redis».
«Портрет программиста, десять лет взлетов и падений»
Самая полезная серия:
«Наиболее часто используемый набор навыков «vim» в производственной среде Linux.
«Наиболее часто используемый набор навыков «Sed» в производственной среде Linux.
«Наиболее часто используемый набор навыков «AWK» в производственной среде Linux.
Вы можете знать, что системы с высоким параллелизмом нуждаются в ограничении тока, но что это за конкретное ограничение и как его сделать, вы все равно можете скопировать его. Затем мы систематически классифицируем его в небольшую категорию, надеясь помочь вам.
Текущая ограничивающая реализация представлена в google guava: RateLimiter, этот класс очень тонко разработан и может применяться к большинству наших повседневных дел.流控
Однако из-за разнообразия сценариев использования его также необходимо использовать с большой осторожностью.
Ранее он был разогрет двумя простыми статьями.
Ограничение семафора, сценарии с высокой степенью параллелизма должны раскрыть секрет
Без предварительного нагрева, не называется высоким параллелизмом, называется высоким параллелизмом
На этот раз все по-другому. В этой статье подробно и всесторонне будут представлены различные сценарии и свойства текущего ограничителя, а затем проанализирован основной исходный код guava, текущего ограничителя, и обобщены его характеристики. Это немного продвинутая продвинутая глава.
Сценарии ограничения тока
Выяснение того, какие ресурсы вы хотите ограничить, является наиболее важной частью процесса. Обычно я делю его на три категории.
прокси-уровень
Например, SLB, nginx или шлюз бизнес-уровня и т. д. поддерживают ограничение тока, обычно основанное на连接数
(Или включены),请求数
Ограничить ток.限流的维度通常是基于比如IP地址、资源位置、用户标志等。更进一步,还可以根据自身负载情况动态调整限流的策略(基准)。
служебный абонент
Вызывающую службу также можно назвать локальным ограничением тока.Клиент может ограничить скорость вызова удаленной службы.Если она превышает пороговое значение, он может напрямую заблокировать или отклонить ее, что является ограничением тока.协作方
.
Получатель услуги
В основном то же самое, что и выше, когда трафик превышает пропускную способность системы, она напрямую отказывает в обслуживании. Обычно исходя из надежности самого приложения, это ограничивающий ток主体方
.我们常说的限流,一般发生在此处。本文主要结合RateLimiter讨论基于限流主体方的使用方式,其他的都类似。
Текущая стратегия ограничения
Текущая стратегия дросселирования иногда проста, а иногда сложна, но есть три наиболее распространенных. Все остальное является улучшением и расширением вдобавок к этому.
Текущее регулирование на основе уровня параллелизма
Это простой и легкий в реализации способ регулирования, который можно реализовать с помощью семафора Java, о котором мы упоминали ранее. Сценарии его использования также имеют относительно разные характеристики:
1) Для каждого запроса требуемые затраты ресурсов относительно сбалансированы.Например, потребление ЦП и потребление ввода-вывода для каждого запроса одинаковы, а запрошенное время RT в основном близко.
2) Плотность запросов либо разреженная, либо высокая частота, на это мы не обращаем внимания.
3) Сам ресурс не требует утомительной работы по инициализации (预热
Расходы) или инициализация можно игнорировать. (Добавляет сложность)
4) Стратегия борьбы с переполнением трафика относительно проста, обычно直接拒绝
а не ждать, потому что ожидание часто означает неудачу.
Эта стратегия обычно применяется к компонентам трафика верхнего уровня, таким как прокси-уровень, промежуточное ПО и т. д., чтобы ограничить количество одновременных подключений. Период ожидания для попытки получить учетные данные называется溢出等待
. Это очень высококлассное и похожее на б слово, верно?
алгоритм дырявого ведра
Запрос трафика для обращения за ресурсами с неопределенной скоростью и обработка программы с постоянной скоростью — основной принцип алгоритма дырявого ведра. Что-то вроде процесса приготовления мороженого. --.- Что касается модели дырявого ведра, вы можете изучить соответствующую информацию.
Обычно существуют следующие понятия.
Ковшовый буфер
Запрос сначала пытается попасть в очередь, и если очередь заполнена, запрос отклоняется. После поступления в очередь запрос ожидает выполнения.
Видно, что есть еще какие-то переменные при выполнении запроса, что напрямую зависит от количества отложенных запросов в очереди. Иногда проницательные разработчики рассматривают возможность увеличения порога времени для ограничения ожидания запроса, который представляет собой максимальную разницу во времени между постановкой запроса в очередь и удалением из очереди. Размер буфера обычно напрямую зависит от скорости.
Слив: запрос на удаление из очереди
Эта команда немного специфична, и реализация разных дизайнерских концепций отличается. имеют抢占式
,имеют调度式
.其中“抢占式”就是处理线程(或者进程,比如nginx worker进程)在上一个请求处理完毕之后即从buffer队列中poll新的请求,无论当前线程(或者进程)的处理速率是否超过设定的速率,这种策略下buffer大小就限定了速率的上限。
Планирование проще для понимания, оно требует дополнительных потоков планирования (процессов), получает запросы из буфера в строгом соответствии с установленной скоростью и циклически передает запросы другим рабочим потокам. busy , затем напрямую создайте новый поток, цель которого состоит в том, чтобы обеспечить гарантированную скорость, таким образом, размер буфера в основном зависит от времени ожидания.
переполнение
Это связано с тем, что предел скорости дырявого ведра относительно стабилен, поэтому он почти не справляется с всплесками трафика, короче говоря, если буфер превышен, он будет отклонен напрямую.
Какие плохие петиции.
Трафик взрывается
Хоть конструкция буфера и учитывает всплески трафика на определенном уровне, но он все равно слишком хрупок.Например, в определенный момент плотность запросов очень высокая (самое смущающее, что она лишь чуть больше) , а буфер переполнен, а может буфер "больше". "Немного" можно обработать за разумное время, у запрашивающей стороны будет некоторая путаница, "я чуть-чуть превысил, а вы мне дали серия нерабочих сообщений, так что наивно!!!".
Эта стратегия также очень часто используется, но обычно она применима к сотруднику по ограничению тока, который также находится на уровне клиента. Перед отправкой запроса выполните контроль потока, если есть переполнение, используйте другие надежные стратегии для обеспечения результата, такие как повторная попытка и т. д. В любом случае, "обратный сервис перегружен, не обессудьте, я очень дисциплинирован" ."
корзина с жетонами
Я не буду больше представлять модель дизайна, вы можете перейти на вики, чтобы узнать о ней больше.
Основная идея жетонного ведра такая же, как и в эпоху коллективной коммуны старшего поколения.Ежемесячное предложение и продажа ограничены, а ресурсы распределяются между отдельными лицами.Нехватка будет обсуждаться в следующем месяце, и вы можете встать в очередь в кредит.
Количество токенов — это количество запросов, которые могут быть разрешены для получения ресурсов (мы предполагаем, что для каждого запроса требуется только один токен). На самом деле мы не создаем сущность токена, потому что это не нужно, мы используем счетчик с функцией времени для представления количества доступных токенов. По сравнению с алгоритмом дырявого ведра «ведро» ведра с токенами не используется для буферизации запросов, а используется для измерения количества доступных ресурсов (токенов). Хотя мы не будем создавать сущность токена, мы все же можем представить, что определенное количество токенов будет добавляться в ведро каждый раз X. Если нет запроса на токен, то ведро токенов переполнится... Вы обнаружите, что этот дизайн противоположен алгоритму дырявого ведра со стороны ввода-вывода.
Тогда недостаток алгоритма дырявого ведра также оказывается особенностью ведра для токенов: трафик резко увеличивается, ведро для токенов становится буфером, если плотность запросов низкая или он находится в состоянии охлаждения, то ведро для токенов переполняется. в случае взрыва избыточные ресурсы, накопленные в прошлом, могут быть напрямую «заимствованы».
Алгоритм Token Bucket имеет множество сценариев использования и высокую степень адаптивности.В действительности всплески трафика являются обычным явлением, и с точки зрения дизайна, Token Bucket проще реализовать. Возвращаясь к теме, RateLimiter — это реализация, основанная на идее бакетов токенов.
Наш рот становится все меньше и, наконец, получает тему.
RateLimiter
API Guava более четко объяснил свою идею дизайна, но этот комментарий все еще немного «философский», чтобы прочитать. Давайте сначала посмотрим на два каштана, а затем посмотрите на его принцип дизайна с уровня исходного кода.
//RateLimiter limiter = RateLimiter.create(10,2, TimeUnit.SECONDS);//QPS 100
RateLimiter limiter = RateLimiter.create(10);
long start = System.currentTimeMillis();
for (int i= 0; i < 30; i++) {
double time = limiter.acquire();
long after = System.currentTimeMillis() - start;
if (time > 0D) {
System.out.println(i + ",limited,等待:" + time + ",已开始" + after + "毫秒");
} else {
System.out.println(i + ",enough" + ",已开始" + after + "毫秒");
}
//模拟冷却时间,下一次loop可以认为是bursty开始
if (i == 9) {
Thread.sleep(2000);
}
}
System.out.println("total time:" + (System.currentTimeMillis() - start));
Этот пример представляет собой простое управление потоком, есть только один ресурс, и QPS10
; В реальных бизнес-сценариях разные скорости ресурсов могут быть разными, и мы можем создать N нескольких счетчиков для обслуживания ресурсов каждый.
Метод Acquire() заключается в получении токена (с использованием разрешения, лицензии в исходном коде), если разрешения достаточно, возврат без ожидания, если недостаточно, ожидание 1/QPS секунды.
Кроме того, вы обнаружите, что,Limiter не имеет метода release(), аналогичного механизму блокировки., что означает «пока вы подаете заявку, вы всегда добьетесь успеха», и вам не нужно возвращать ее при отзыве.
Внутри RateLimiter есть две реализации: (здесь и далее «ресурсы», «токены» и «разрешения» имеют одно и то же значение)
SmoothBursty
Ограничитель тока, который может поддерживать "пакетный трафик", то есть, когда текущий ограничитель не используется, можно хранить дополнительные разрешения для пакетного трафика. При возникновении пакетного трафика ресурсы можно использовать быстрее и полнее. После того, как трафик стабильный (или период восстановления, после того, как накопленные разрешения будут израсходованы) скорость ограничена.
Дело в том, что во время кулдауна разрешения будут накапливаться, и в случае всплеска трафика ранее накопленные разрешения могут быть израсходованы без ожидания. Так же, как и человек, после пробежки вы можете немного отдохнуть и начать снова, чтобы иметь более высокую скорость.
Таким образом, если ваши ресурсы после охлаждения (не используются) в течение некоторого времени, когда снова используются для обеспечения более высокой эффективности, чем обычно, на этот раз вы можете использовать SmoothBursty.
как создать
RateLimiter.create(double permitsPerSecond)
Похожие результаты
0,enough,已开始1毫秒
1,limited,等待:0.098623,已开始105毫秒
2,limited,等待:0.093421,已开始202毫秒
3,limited,等待:0.098287,已开始304毫秒
4,limited,等待:0.096025,已开始401毫秒
5,limited,等待:0.098969,已开始505毫秒
6,limited,等待:0.094892,已开始605毫秒
7,limited,等待:0.094945,已开始701毫秒
8,limited,等待:0.099145,已开始801毫秒
9,limited,等待:0.09886,已开始905毫秒
10,enough,已开始2908毫秒
11,enough,已开始2908毫秒
12,enough,已开始2908毫秒
13,enough,已开始2908毫秒
14,enough,已开始2908毫秒
15,enough,已开始2908毫秒
16,enough,已开始2908毫秒
17,enough,已开始2908毫秒
18,enough,已开始2908毫秒
19,enough,已开始2908毫秒
20,enough,已开始2909毫秒
21,limited,等待:0.099283,已开始3011毫秒
22,limited,等待:0.096308,已开始3108毫秒
23,limited,等待:0.099389,已开始3211毫秒
24,limited,等待:0.096674,已开始3313毫秒
25,limited,等待:0.094783,已开始3411毫秒
26,limited,等待:0.097161,已开始3508毫秒
27,limited,等待:0.099877,已开始3610毫秒
28,limited,等待:0.097551,已开始3713毫秒
29,limited,等待:0.094606,已开始3809毫秒
total time:3809
SmoothWarmingUp
Он имеет характеристику прогрева, то есть, когда происходит всплеск трафика, максимальная скорость не может быть достигнута сразу, а должна постепенно увеличиваться в течение заданного «времени прогрева» и, наконец, достигать порога; философия его конструкции, наоборот до SmoothBursty, когда возникает внезапный трафик. Когда возникает трафик, ресурсы используются постепенно с управляемой медленной скоростью (до самой высокой скорости), и скорость ограничивается после того, как трафик стабилизируется.
Дело в том, что если ресурс используется все время, он может и дальше ограничивать стабильную скорость, в противном случае, чем больше время охлаждения (эффективное время — интервал прогрева), тем дольше время ожидания получения разрешений, он должен Обратите внимание, что время охлаждения будет накапливать разрешения, но получение этих разрешений по-прежнему требует ожидания.
Видно, что если ваш ресурс охлаждается (не используется) в течение определенного периода времени, он нуждается в определенной подготовительной работе, когда он снова используется, и эффективность, которую он может обеспечить, ниже, чем обычно в это время; например, пул ссылок , кеш базы данных и т.д.
как создать
RateLimiter.create(double permitsPerSecond,long warnupPeriod,TimeUnit unit)
Результаты выполнения следующие, и видно, что идет очевидный процесс роста.
0,enough,已开始1毫秒
1,limited,等待:0.288847,已开始295毫秒
2,limited,等待:0.263403,已开始562毫秒
3,limited,等待:0.247548,已开始813毫秒
4,limited,等待:0.226932,已开始1041毫秒
5,limited,等待:0.208087,已开始1250毫秒
6,limited,等待:0.189501,已开始1444毫秒
7,limited,等待:0.165301,已开始1614毫秒
8,limited,等待:0.145779,已开始1761毫秒
9,limited,等待:0.128851,已开始1891毫秒
10,enough,已开始3895毫秒
11,limited,等待:0.289809,已开始4190毫秒
12,limited,等待:0.264528,已开始4458毫秒
13,limited,等待:0.247363,已开始4710毫秒
14,limited,等待:0.225157,已开始4939毫秒
15,limited,等待:0.206337,已开始5146毫秒
16,limited,等待:0.189213,已开始5337毫秒
17,limited,等待:0.167642,已开始5510毫秒
18,limited,等待:0.145383,已开始5660毫秒
19,limited,等待:0.125097,已开始5786毫秒
20,limited,等待:0.109232,已开始5898毫秒
21,limited,等待:0.096613,已开始5999毫秒
22,limited,等待:0.096321,已开始6098毫秒
23,limited,等待:0.097558,已开始6200毫秒
24,limited,等待:0.095132,已开始6299毫秒
25,limited,等待:0.095495,已开始6399毫秒
26,limited,等待:0.096352,已开始6496毫秒
27,limited,等待:0.098641,已开始6597毫秒
28,limited,等待:0.097883,已开始6697毫秒
29,limited,等待:0.09839,已开始6798毫秒
total time:6798
Анализ исходного кода метода получения
Вышеуказанные два класса наследуются от SmoothRateLimiter и, наконец, от RateLimiter; внутренние основные методы RateLimiter:
1) двойное приобретение (): получить разрешение и вернуться напрямую, если разрешений достаточно, в противном случае подождите 1/QPS в секунду. Этот метод возвращает время (в секундах), которое поток ожидает, если он возвращает 0.0, это означает, что нет текущего ограничения и нет ожидания.
2) двойное получение (int n): получение n разрешений, если разрешений достаточно, возврат напрямую, в противном случае ограничение тока и ожидание, время ожидания равно «количеству недостаточных разрешений / QPS». (Давайте объясним это так)
Ниже приведен псевдокод этого метода.
//伪代码
public double acquire(int requiredPermits) {
long waitTime = 0L;
synchronized(mutex) {
boolean cold = nextTicketTime > now;
if (cold) {
storedPermits = 根据冷却时长计算累积的permits;
nextTicketTime = now;
}
//根据storedPermits、requiredPermits计算需要等待的时间
//bursty:如果storePermits足够,则waitTime = 0
//warmup:平滑预热,storePermits越多(即冷却时间越长),等待时间越长
if(storedPermits不足) {
waitTime += 欠缺的permits个数 / QPS;
}
if(bursty限流) {
waitTime += 0;//即无需额外等待
}
if(warmup限流) {
waitTime += requiredPermits / QPS;
if(storedPermits > 0.5 * maxPermits) {
waitTime += 阻尼时间;
}
}
nextTicketTime += waitTime
}
if (waitTime > 0L) {
Thread.sleep(waitTime);
}
return waitTime;
}
Следующий контент будет относительно скучным~~ Очень скучным~~
1. Объектный мьютекс: блокировка синхронизации, как показано в приведенном выше псевдокоде, вся синхронизируется в процессе расчета разрешений на акции и фактической подачи заявок на разрешения (включая расчет); нам нужно знать, что механизм синхронизации блокировки действительно используется внутри RateLimiter .
2, Maxpermits: максимальное количество лицензий, которые могут быть сохранены (количество билетов), сглаженные и управленные реализации по умолчанию:
1) SmoothBusty, значение которого равно maxBurstSecond * QPS, позволяет разрешить "продолжительность пакетного трафика" * QPS, этот дизайн понятен, но RateLimiter жестко кодирует maxBustSecond до 1,0, и, наконец, это значение равно QPS.
2) SmoothWarmingUp: значение алгоритма по умолчанию — WarmupPeriod * QPS, то есть просто «продолжительность прогрева» * QPS.
Этот параметр в основном ограничен, независимо от того, как долго время охлаждения, его StoredPermits не может превышать это значение, это значение не изменится после установки QPS.
3. storagePermits: количество сохраненных разрешений.Это значение зависит от времени охлаждения.Короче говоря, чем дольше время охлаждения, тем больше значение, но оно не будет превышать maxPermits, а начальное значение равно 0.
1) При подаче запроса, перед подачей заявки на разрешение, будет рассчитана разница во времени между временем последней заявки на токен (nexFreeTicketTime) и текущим моментом, а токены, которые можно хранить в течение этого периода охлаждения, будут рассчитаны в соответствии с скорость генерации токена (1/QPS).число, в котором хранятся разрешения.
2) После того, как приложение Permits завершено, текущее время (если вам нужно подождать, дополнительное время ожидания) в качестве времени начала следующего применения токена, после чего время охлаждения заканчивается.
3) После того, как приложение будет завершено, сохраненные разрешения будут вычтены из количества примененных разрешений, пока оно не станет равным 0.
Время охлаждения и частота приложений определяют размер storePermits.Время охлаждения увеличивает storePermits, а операция получения уменьшает storePermits.
4. nextFreeTicketMicros (timestamp, micro unit): время следующего токена, который можно свободно получить, это значение может быть определенное время в будущем, в это время, это означает, что текущий лимит начался, и некоторые запросы уже ожидает, это значение в основном используется для обозначения «состояния охлаждения». (кредит)
1) Если он находится в периоде остывания, то это значение обычно прошедшее время, то есть это значение меньше, чем сейчас.
2) Если в это время есть запрос на подачу заявки на получение разрешений, сохраненные разрешения будут рассчитываться на основе разницы во времени между этим значением и настоящим, и это значение будет установлено на настоящее время.
3) Если это значение относится к будущему моменту, т.е. больше, чем сейчас, нет необходимости ни вычислять сохраненные разрешения, ни сбрасывать это значение.
4) После подачи заявки на билеты вычтите необходимое количество билетов из сохраненных разрешений.Если срабатывает ожидание ограничения скорости (например, период прогрева, недостаточное количество разрешений), 2) Дополнительное время ожидания после операции будет использоваться как nextFreeTicketsTime ценность.
5) Исходя из 2), для ограничения тока прогрева, первый запрос после периода охлаждения не нужно ждать, просто установите это значение сейчас + время ожидания waitTime() демпфирующего характера, а значит будет больше не будет времени ожидания в течение waitTime после этого запроса, он вызовет ожидание и продолжит продолжение со значением nextFreeTicketMicros. Продолжение этого значения, в период прогрева, вычисление демпфирования waitTime более сложное, на 1/QPS + дополнительное значение, это дополнительное значение уменьшается по мере увеличения времени прогрева.
6) На основании 2) для ограничения импульсного тока, если storePermits больше 0, всегда нет необходимости ждать, просто установите это значение сейчас; в противном случае рассчитайте время, которое должно быть задержано в соответствии с нормальным 1/ Точка интервала QPS.
5. Для лимита тока прогрева используйте maxPermits * 0.5 в качестве пороговой разделительной линии, когда storePermits меньше этой разделительной линии, используйте нормальное время ожидания (количество примененных разрешений / QPS) при ограничении тока, когда оно выше этой разделительной линии , то 4) добавить дополнительное демпфирование, то есть демпфирование прогрева.
6. Мы обнаружили, что RateLimiter на самом деле не генерирует сущности тикетов, а только вычисляет биржевые тикеты (соответствующие storePermits) по времени охлаждения и при подаче заявки на ресурсы. Независимо от текущего лимита, сначала используются разрешённые разрешения.
краткое содержание
Время закругляться.
RATELIMITER является безопасным потоком, поэтому его можно использовать непосредственно в одновременной среде без дополнительных блокировков или синхронизации.
Учитывая блокировку синхронизации внутри RateLimiter, в реальной бизнес-разработке каждый ресурс (например, URL) использует свой RateLimiter вместо общего, а занимаемая память невелика.
Внутри текущего ограничителя нет лишних потоков и нет другой структуры данных для хранения объекта тикетов, поэтому он очень легкий, что тоже является преимуществом.
Самая большая проблема с RateLimiter заключается в том, что метод получения всегда будет успешным, а точка времени внутренних заявок будет двигаться назад;Если уровень параллелизма высок и пороговое значение скорости серьезно превышено, время ожидания последующих регулируемых запросов будет накапливаться на основе временной шкалы, что приводит к неконтролируемому времени ожидания, аналогичному семафору.
Чтобы избежать вышеперечисленных проблем, мы обычно сначала используем tryAcquired для обнаружения, а затем переходим к получению, если это возможно; если токена недостаточно, он будет соответствующим образом отклонен. такНа основе RateLimiter нет встроенной политики отклонения, что требует дополнительной разработки.
Мы не можем просто полагаться на метод Acquisition для реализации ограниченных по току ожиданий, иначе это может привести к серьезным проблемам. Обычно нам нужно инкапсулировать RateLimiter и использовать дополнительные атрибуты для записи того, находится ли он «в состоянии ограничения тока», «временной момент отложенных билетов», если «отложенный момент времени очень далеко» и превышает допустимый диапазон, тогда напрямую отклонить запрос. Проще говоря, инкапсулируйте метод Acquisition, чтобы увеличить оценку возможного времени ожидания запроса.Если оно слишком велико, оно будет отклонено напрямую.
Большая проблема с RateLimiter заключается в том, что его практически невозможно расширить: все подклассы защищены. Кроме отражения.
практика
Вернемся к предыдущему фрагменту кода, там более наглядно видно, что мы сделали: FollowCotroller.java: контроллер потока, если начинается текущий лимит, этого будет ждать только max запросов, а если превысит это значение, то будет быть отвергнутым напрямую
public class FollowController {
private final RateLimiter rateLimiter;
private int maxPermits;
private Object mutex = new Object();
//等待获取permits的请求个数,原则上可以通过maxPermits推算
private int maxWaitingRequests;
private AtomicInteger waitingRequests = new AtomicInteger(0);
public FollowController(int maxPermits,int maxWaitingRequests) {
this.maxPermits = maxPermits;
this.maxWaitingRequests = maxWaitingRequests;
rateLimiter = RateLimiter.create(maxPermits);
}
public FollowController(int permits,long warmUpPeriodAsSecond,int maxWaitingRequests) {
this.maxPermits = maxPermits;
this.maxWaitingRequests = maxWaitingRequests;
rateLimiter = RateLimiter.create(permits,warmUpPeriodAsSecond, TimeUnit.SECONDS);
}
public boolean acquire() {
return acquire(1);
}
public boolean acquire(int permits) {
boolean success = rateLimiter.tryAcquire(permits);
if (success) {
rateLimiter.acquire(permits);//可能有出入
return true;
}
if (waitingRequests.get() > maxWaitingRequests) {
return false;
}
waitingRequests.getAndAdd(permits);
rateLimiter.acquire(permits);
waitingRequests.getAndAdd(0 - permits);
return true;
}
}
Приведенный выше код можно найти на github.
https://github.com/sayhiai/example-ratelimit
End
Как видите, гуава предоставляет очень легкий и всеобъемлющий ограничитель тока. Он не реализован с использованием самой многопоточности, но является потокобезопасным. По сравнению с семафорами он намного проще в использовании. Но учитывая разнообразие сценариев ограничения тока, будьте очень осторожны при его использовании.
Больше отличных статей.
Минервисты не все, просто подмножество определенного домена
С таким количеством компонентов мониторинга всегда найдется подходящий для вас
"Подтаблица подбиблиотеки"? Выбор и процесс должны быть осторожны, иначе он выйдет из-под контроля
С Нетти, что именно мы разрабатываем?
В производственной среде Linux наиболее часто используемый набор навыков «vim».