NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

Úložisko (Store) uchováva časové značky požiadaviek, voči ktorým sa limit meria. Každé úložisko overí požiadavku voči všetkým oknám limitu (aj prípadnej adaptívnej penalizácii) a zapíše ju jedným atomickým krokom — Store::attempt() —, takže dva workery nikdy neobsadia to isté posledné voľné miesto. Vyberte ho podľa toho, ako široko sa má limit zdieľať:

ÚložiskoZdieľané medziPoznámky
InMemoryStoreVšetkými limitmi v jednom procesePredvolené. Bez nastavenia; jednu inštanciu zdieľajú všetky limity aplikácie, no každý worker či server počíta zvlášť.
CacheStoreVšetkými procesmi s rovnakou cacheĽubovoľná cache (file, database, memcached, redis, array). Kontrola a zápis prebehnú pod atomickým zámkom cache — poskytuje ho každý vstavaný cache store Laravelu.
RedisStoreProcesmi aj servermiSorted set pre každé okno; kontrola a zápis bežia ako jeden Lua skript. Používa redis_connection.
DatabaseStoreProcesmi aj servermiDve tabuľky cez Eloquent; každý pokus je krátka transakcia so zámkom. Používa database_connection. Najprv publikujte a spustite migráciu.

InMemoryStore

Predvolené. Uchováva časové značky v pamäti procesu. Jednu inštanciu zdieľajú všetky limity, ktoré aplikácia vytvorí, takže samostatné volania Http::rateLimit() sa v rámci procesu sčítavajú do jedného limitu. Platí však len v rámci procesu: každý worker vo fronte, PHP-FPM proces či server počíta zvlášť, preto pri viacerých workeroch použite CacheStore, RedisStore alebo DatabaseStore. Atomické je preto, že ho mimo procesu nikto nevidí.

CacheStore

Zdieľa limity medzi procesmi cez cache, ktorú aplikácia už používa (file, database, memcached, array, …) — Redis nie je potrebný. Kontrola a zápis prebehnú pod atomickým zámkom cache (jeden pre každé okno, berú sa v pevnom poradí), ak cache store poskytuje zámky — každý vstavaný cache store Laravelu ich poskytuje; vlastný store bez zámkov funguje len best-effort. Zámok sa drží najviac lockSeconds (predvolene 5) a rovnako dlho naň zapisovateľ čaká, kým vyhodí LockTimeoutException od Laravelu. Nastavíte ho kľúčmi cache_store / cache_prefix alebo vytvoríte priamo:

use RoundlyConsulting\HttpClientRateLimits\Store\CacheStore;

$store = new CacheStore(store: 'redis', prefix: 'http-client-rate-limits');

Cache typu file (aj jej zámky) platí len na jednom serveri; ak má limit platiť naprieč servermi, použite cache database, redis alebo memcached.

RedisStore

Uchováva časové značky v sorted setoch (každý pokus je unikátny člen, takže sa započítajú aj pokusy v tej istej milisekunde) zdieľaných medzi procesmi aj servermi. Celá kontrola so zápisom je jeden Lua skript, ktorý Redis vykoná bez prerušenia iným príkazom. Kľúče sú označené hash tagom podľa kľúča limitu (http-client-rate-limits:{acct-1}:second), takže v Redis Cluster ležia okná aj penalizácia limitu v jednom slote; zložený limit, ktorého okná používajú rôzne kľúče, potrebuje Redis s jedným uzlom. Odovzdajte názov Redis spojenia (predvolene default):

use RoundlyConsulting\HttpClientRateLimits\Store\RedisStore;

$store = new RedisStore('default');

DatabaseStore

Zdieľa limity cez dve databázové tabuľky (cez Eloquent, nikdy nie fasádu DB) — pre aplikácie len s file alebo database cache a bez Redisu. Každý pokus je krátka transakcia, ktorá najprv zapíše riadok kľúča limitu v http_client_rate_limit_owners — zámok riadku na MySQL/MariaDB a Postgres, zámok zápisu na SQLite —, takže pokus druhého workera o ten istý kľúč počká, kým prvý overí aj zapíše. Zvolíte ho cez 'store' => DatabaseStore::class a publikujete a spustíte jeho migráciu (pozrite Inštalácia):

use RoundlyConsulting\HttpClientRateLimits\Store\DatabaseStore;

$store = new DatabaseStore;                       // the default connection
$store = new DatabaseStore(connection: 'limits'); // or `database_connection` in config

Ak môžu obmedzované volania bežať vo vašej vlastnej transakcii, dajte mu samostatné spojenie (database_connection): na spoločnom spojení sa transakcia úložiska vnorí do vašej, takže jeho zámok drží — a jeho pokus ostáva pre ostatné workery neviditeľný —, kým vaša transakcia neskončí commitom.

Uchovávanie a penalizácie

Každé vstavané úložisko samo odstraňuje záznamy staršie ako najväčšie podporované okno (jeden deň s hodinovou rezervou), takže dlhodobé kľúče — aj tabuľky DatabaseStore — nerastú donekonečna. Každé úložisko navyše ukladá penalizácie od servera pre adaptívne obmedzovanie cez penalizeUntil() / penalizedUntil().

Vlastné úložisko

Implementujte kontrakt Store a svoju triedu zvoľte v konfigurácii, cez RateLimits::usingStore() alebo setStore(). Jeho attempt() znamená „vezmite si zámok, opýtajte sa RoundlyConsulting\HttpClientRateLimits\Support\Windows::evaluate() a pri povolení zapíšte“:

namespace RoundlyConsulting\HttpClientRateLimits\Store;

use RoundlyConsulting\HttpClientRateLimits\DataTransferObjects\AttemptResult;
use RoundlyConsulting\HttpClientRateLimits\Limit;

interface Store
{
    // Check every window and, only when none is full and no penalty is active,
    // record the hit — as ONE atomic step. Otherwise record nothing and say how long to wait.
    /** @param list<Limit> $limits */
    public function attempt(array $limits, int $timestamp): AttemptResult;

    // Record a hit unconditionally (no check).
    public function hit(string $owner, int $timestamp): void;

    /** @return list<int> */
    public function hits(string $owner): array;

    /** @return list<int> */
    public function hitsSince(string $owner, int $timestamp): array;

    public function clear(string $owner, int $timestamp): void;

    // Server-imposed "do not send again before" timestamp (ms) for adaptive limiting.
    public function penalizeUntil(string $owner, int $timestamp): void;

    public function penalizedUntil(string $owner): ?int;
}

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.