CodeGym /Kurslar /ChatGPT Apps /Şlüz və perimetrin mühafizəsi: proxy, rate limiting, növb...

Şlüz və perimetrin mühafizəsi: proxy, rate limiting, növbələr və backpressure

ChatGPT Apps
Səviyyə , Dərs
Mövcuddur

1. Niyə ümumiyyətlə ChatGPT App perimetrini qorumaq lazımdır

Klassik veb‑tətbiqdə istifadəçi — sizin endpoint‑lərinizə kifayət qədər proqnozlaşdırıla bilən şəkildə müraciət edən brauzerdir. ChatGPT Apps dünyasında isə sizdə yeni tip müştəri peyda olur: LLM, hansı ki, alətləri nə zaman və hansını çağıracağını özü qərar verir.

Model bunları edə bilər:

  • bir dialoqda eyni tool‑u ardıcıl bir neçə dəfə çağırmaq;
  • eksperiment aparmaq: “bəs bir də suggest_gifts‑i bir az fərqli parametrlərlə çağırsam necə olar?”;
  • yüzlərlə istifadəçi üçün paralel işləmək.

Buna ehtimal olunan botları, test skriptlərini, öz kodunuzdakı xətaları (məsələn, tool‑call‑ı daimi tetikləşdirən sonsuz dövr) də əlavə edin — və siz xoş niyyətlə edilən demək olar ki, ideal bir DoS resepti əldə edəcəksiniz.

Üstündəki albalı isə — qiymətdir. Hər bir tool‑call:

  • xarici ödənişli API‑lərdən istifadə edə bilər (kuryerlər, ödənişlər, kataloqlar),
  • başqa LLM‑ləri çağırır (məsələn, RAG axtarışı),
  • ağır fond tapşırıqlarını işə salır.

Məhdudiyyət və perimetr mühafizəsi olmadan, tək bir “uğursuz” müştəri aşağıdakıları edə bilər:

  • gateway arxasındakı bütün backend‑xidmətlərinizi yıxa bilər (Gift API, Commerce API və s.),
  • xarici API limitlərinizi tükəndirə bilər,
  • və model büdcənizi ciddi şəkildə yandıra bilər.

Bu mühazirənin məqsədi — gateway/proxy + rate limiting + növbələr + backpressure sayəsində bu potensial fəlakəti idarə olunan sistemə çevirməyin yollarını göstərməkdir.

Insight

ChatGPT platforması heç bir müdafiə mexanizmi təqdim etmir ki, MCP serverinizi xarici trafikin qarşısından qorusun. İstənilən internet‑müştəri ona sorğu göndərə bilər; buna MCP Jam kimi utilitlər də daxildir.

ChatGPT‑nin sizə təklif edə biləcəyi yeganə şey — tərs proxy (məsələn, NGINX) üzərində allowlist quraraq daxil olan trafiki IP ünvanlara görə məhdudlaşdırmaqdır. IP filtrasiyası qurulmayıbsa, MCP serveriniz tam açıq qalır ki, bu da təhlükəsiz deyil. Nə sizin, nə də istifadəçiləriniz üçün.

2. Proxy/Gateway backend‑xidmətlər və agentlər qarşısında “qalxan” kimi

Əvvəlcə şəkli xatırladaq, amma bu dəfə müdafiə prizməsindən.

Tipik sxemi təsəvvür edin:

flowchart LR
  ChatGPT["ChatGPT / Widget"]
    --> GW["MCP Gateway (Auth, Rate Limit, Logs)"]

  GW --> GiftAPI["Gift REST API (hədiyyələrin seçimi)"]
  GW --> CommerceAPI["Commerce REST API (checkout, ACP)"]
  GW --> Analytics["Analytics Service / REST API"]

  GW --> Queue["Tapşırıq növbəsi"]
  Queue --> Worker["Background workers"]

Gateway xarici dünya (ChatGPT, webhook‑lar, test müştəriləri) və qalan hər şey arasında dayanır. O:

  • daxil olan bütün sorğuları görür;
  • ilk olaraq tokeni və sorğunun formatını yoxlayır;
  • aşkar mümkün olmayan şeyləri atmağı bacarır (saxta host, qəribə path, həddən artıq böyük body);
  • sorğunu hansı daxili REST‑/HTTP‑xidmətinə göndərməyin mənalı olduğuna qərar verir.

Elə bu səviyyədə aşağıdakılar da peyda olur:

  • rate limiting — müəyyən zaman intervalında neçə sorğuya icazə verdiyimizi məhdudlaşdırırıq;
  • ən sadə backpressure — daxildəki xidmətlər boğulursa, imtina edirik;
  • asinxronluğa keçid — ağır işləri dərhal növbəyə atırıq, müştəriyə cavab: “qəbul edildi, gözləyin”.

Yəni gateway təkcə “router” deyil, həm də “zirehli jilet”dir. Əsas odur ki, onu “bütün biznesin monoliti”nə çevirməyəsiniz — bunu keçən mühazirədə artıq danışmışdıq.

3. Nəqliyyat axınlarından hansını nəzarətdə saxlamaq lazımdır

ChatGPT App ekosistemində adətən məhdudiyyət və müdafiə baxımından bizi maraqlandıran üç əsas trafik tipi var.

Birincisi, bu, ChatGPT‑dən gələn MCP tool‑call‑lar. Bunlar MCP protokolu ilə gələn hər şeydir: suggest_gifts, get_product_details, create_checkout_session və digər alət çağırışları. Model onları kifayət qədər sürətlə generasiya edə bilər, xüsusən də altında Agents olduqda.

İkincisi, bu, backend‑lərimizin xarici API‑lərə çıxan sorğularıdır. Xidmətin içində kataloqlar, logistika, ödənişlər kimi kənar sistemlərə öz rate limitlərimiz ola bilər. Onları pozmaq — bloklanma, cərimə və ya keyfiyyətin düşməsi deməkdir.

Üçüncüsü, bu, daxil olan webhook‑lardır — ACP, ödəniş provayderləri (Stripe və s.), kuryerlərdən bildirişlər. Onlar istifadəçi aktivliyindən asılı olmayaraq gəlir. Əgər bizim endpoint ləng işləyirsə və ya səhv qaytarırsa, xarici sistem təkrar cəhdlər (retries) edəcək və sizə təkrar bildirişlərdən ibarət “fırtına” yarada bilər.

GiftGenius üçün bu belə görünür:

  • istifadəçi və model aktiv şəkildə suggest_giftsfind_similar_gifts‑i çağırırlar;
  • checkout aləti ACP/kommersiya backend‑ini çağırır;
  • ödəmədən sonra ödəniş sistemi payment.succeeded / payment.failed webhook‑larını göndərir.

Bütün bu axınlar bir nöqtədə — Gateway‑də birləşir; deməli, məhz orada “sayğaclar, filtr və tıxaclar” qoymaq məntiqlidir.

4. Rate limiting: bazaya müdafiə və büdcəyə qənaət

Bizim kontekstdə rate limiting nədir

Rate limiting — müəyyən bir müştərinin vahid vaxtda göndərə biləcəyi sorğuların sayını məhdudlaşdıran mexanizmdir. Fikir internet qədər qədimdir, amma ChatGPT Apps kontekstində dərhal üç məsələni həll edir:

  • bir müştərinin (və ya xətanın) xidmətlərinizi yıxmasına imkan vermir;
  • xarici API limitlərinə riayət etməyə kömək edir;
  • modellərin nəzarətsiz çağırışlarından büdcənizi qoruyur.

Klassik alqoritmlər:

  • sabit pəncərə (Fixed Window),
  • sürüşən pəncərə (Sliding Window),
  • token vedrəsi (Token Bucket),

bizim üçün daha çox konseptual bilik vacibdir: “bir dəqiqədə N sorğudan çox deyil”, “hər sorğu bir token sərf edir, tokenlər saniyədə X sürətlə dolur” və s. Realizasiyanı adətən kitabxana və ya API Gateway edir.

Limitləri harada qoymalı

Limitləri müxtəlif səviyyələrdə qoymaq olar.

Tərs proxy səviyyəsində (Nginx, Cloudflare, AWS API Gateway) rahatdır:

  • ən vəhşi trafiki IP üzrə kəsmək;
  • sorğunun bədəninin ölçüsünü məhdudlaşdırmaq;
  • sadə DDoS‑naxışlarından qorunmaq.

MCP Gateway (tətbiq) səviyyəsində daha “mənalı” rate limiting etmək faydalıdır:

  • istifadəçiyə görə (userId tokenindən),
  • təşkilata görə (tenantId),
  • əməliyyat tipinə görə (məsələn, create_checkout_session sərt, search — daha yumşaq),
  • mənbəyə görə (webhook vs tool‑call).

Və ayrıca, xüsusilə baha başa gələn əməliyyatlar üçün limitləri birbaşa mikroxidmətlərin özündə də əlavə etmək olar, amma bu artıq növbəti detal səviyyəsidir.

Limitlər üçün açarı necə seçməli

Ən geniş yayılmış səhv — IP ünvanına görə məhdudlaşdırmaqdır. ChatGPT halında bu xeyli faydasızdır:

  • bütün sorğular OpenAI diapazonundan gələ bilər,
  • fərqli istifadəçilər eyni IP arxasında “oturacaqlar”.

Bizim üçün daha maraqlıdır:

  • userId — tətbiqinizdə konkret istifadəçi;
  • tenantId — təşkilat (əgər B2B edirsinizsə və bir çatdan bir çox əməkdaş istifadə edirsə);
  • API‑token və ya clientId, əgər bir neçə inteqrasiyanız varsa.

GiftGenius‑da adətən userId + tenantId kifayət edir; onlar ChatGPT‑nin MCP çağırışlarında ötürdüyü tokendən çıxarılır.

TypeScript‑də sadə rate limiting reallaşdırması

Tutaq ki, Express üzərində kiçik bir MCP Gateway‑imiz var. Ora ən sadə rate limiting əlavə edək: bir istifadəçi üçün dəqiqədə 30 tool‑call‑dan çox olmasın.

// Sadə rate limiting: hər userId üçün dəqiqəyə N sorğu
const WINDOW_MS = 60_000;
const MAX = 30;
const hits = new Map<string, { ts: number; count: number }>();

function rateLimit(req: Request, res: Response, next: NextFunction) {
  const userId = (req.headers["x-user-id"] as string) ?? "anonymous";
  const now = Date.now();
  const rec = hits.get(userId) ?? { ts: now, count: 0 };

  if (now - rec.ts > WINDOW_MS) {      // Pəncərə "köhnəlib" - yenidən başlayırıq
    rec.ts = now;
    rec.count = 0;
  }
  rec.count += 1;
  hits.set(userId, rec);

  if (rec.count > MAX) {
    return res.status(429).json({
      error: "rate_limit_exceeded",
      retryAfterSec: 60,
      message: "Too many tool calls, please retry later."
    });
  }
  next();
}

İndi isə onu MCP marşrutunda istifadə edək:

// Bütün MCP tool‑call‑lara middleware tətbiq edirik
app.post("/mcp/tools/call", rateLimit, async (req, res) => {
  const result = await callBackendForTool(req.body); // Gift/Commerce/Analytics API‑yə REST çağırışı
  res.json(result);
});

Açar məqamlar:

  • biz məzmunlu bir səhv qaytarırıq (error: "rate_limit_exceeded"), təkcə 500 deyil;
  • model bu xətanı oxuya, nə baş verdiyini anlaya və istifadəçiyə düzgün izah edə biləcək, uydurmalara başlamayacaq.

Real prodakşnda sayğaclar, əlbəttə, bir prosesin yaddaşında yox, klasterdə işləməsi üçün Redis və ya digər ümumi saxlama yerində yaşayır. Prinsipi anlamaq üçün bu kifayətdir.

Rate limiting və gateway səviyyəsində limitlər bizi sorğu selindən qoruyur, amma başqa bir problemi həll etmir — ayrı əməliyyatlar yenə də çox ağır və uzun icra oluna bilər. Burada artıq təkcə sinxron HTTP kifayət etmir; səhnəyə növbələr və asinxron tapşırıqlar çıxır.

5. Növbələr və asinxron tapşırıqlar: sinxron artıq mümkün olmayanda

ChatGPT taymaut problemi

Rate limiting‑i diqqətlə qursanız belə, ChatGPT (və ümumiyyətlə HTTP‑müştərilər) cavabın çox gec gəlməsini xoşlamır. Platforma tool‑call icra vaxtını məhdudlaşdırır; əgər siz “super‑tövsiyə” alqoritmi bitənə qədər gözləsəniz, o zaman:

  • istifadəçi sonsuz spinner görəcək;
  • platforma sorğunu taymautla kəsəcək;
  • model “nəsə alınmadı” qərarına gəlib izahlar uydurmağa başlayacaq.

Həll: ağır əməliyyatları asinxron rejimə keçirmək. Klassik paternlər:

  1. Gateway sorğunu qəbul edir.
  2. Tapşırığı növbəyə qoyur.
  3. Dərhal 202 Accepted cavabını jobId ilə qaytarır.
  4. Ayrı worker növbədən tapşırıqları götürüb emal edir.
  5. Müştəri (vidcetimiz və ya hətta ChatGPT ayrıca bir tool vasitəsilə) periodik olaraq jobId üzrə statusu soruşur və nəticəni götürür.

ChatGPT App terminlərində bu adətən iki alət kimi görünür: birinci tool sorğunu qəbul edir, tapşırığı növbəyə qoyur və jobId qaytarır; ikinci — modelə və ya vidcetə həmin jobId üzrə statusu öyrənməyə və nəticəni götürməyə imkan verir. Əlavə olaraq, eyni irəliləyiş hadisələrini MCP bildirişləri ilə də dublikat edə bilərsiniz.

GiftGenius üçün mini‑növbə (kod nümunəsi)

Tutaq ki, bizdə onlarla saniyə işləyə bilən ağır bir alət generate_large_gift_report var. Real App‑də o, yalnız jobId qaytara bilər, ayrıca get_report_status tool‑u isə modelə və ya vidcetə həmin jobId üzrə vəziyyəti öyrənməyə və nəticəni götürməyə imkan verər. Gateway səviyyəsində bunun üçün ayrıca növbəli endpoint edəcəyik.

type Job = { id: string; payload: any };
const queue: Job[] = [];
const MAX_QUEUE = 100;

app.post("/mcp/tools/generate_report", (req, res) => {
  if (queue.length >= MAX_QUEUE) {
    return res.status(503).json({
      error: "system_busy",
      message: "System is busy, please retry later."
    });
  }

  const job: Job = { id: crypto.randomUUID(), payload: req.body };
  queue.push(job);
  res.status(202).json({ jobId: job.id, status: "accepted" });
});

Və hər 200 ms‑də bir tapşırıq götürən primitiv worker:

async function processJob(job: Job) {
  // Burada həqiqi backend xidmətini və ya agent iş axınını REST vasitəsilə çağırırıq
  await handleHeavyGiftReport(job.payload);
}

setInterval(async () => {
  const job = queue.shift();
  if (!job) return;
  await processJob(job);
}, 200);

Aydındır ki, bu xeyli sadələşdirilmiş nümunədir:

  • real həyatda növbə Redis, SQS, Kafka və s. üzərində yaşayır;
  • tapşırığın statusu ayrıca saxlanılır ki, onu soruşmaq mümkün olsun;
  • adətən bir neçə worker olur.

Amma konsepsiya artıq aydındır: Gateway sorğunu, hər şey tamamlanana qədər açıq saxlamır. O, qəbul edir, işə qoyur və tez cavab verir.

6. Backpressure: öz növbənizdə boğulmayın

Backpressure rate limiting‑dən nə ilə fərqlənir

Rate limiting ilk növbədə bu suala cavab verir: “vaxt intervalında bir müştəri nə qədər sorğu edə bilər?”. Bu “çox aktiv bir istifadəçi” və ya konkret müştəri tərəfindəki xəta üçün müdafiədir.

Backpressure isə belə deyir: “sistemimiz eyni vaxtda ümumilikdə nə qədər tapşırıq/sorğunu dağılıb‑dağılmadan həzm edə bilər?”. Bu artıq yükün ümumi həcmi haqqındadır, onun kimdən gəldiyindən asılı olmayaraq.

Nümunə:

  • rate limiting: “istifadəçi suggest_gifts‑i dəqiqədə 30 dəfədən tez çağıra bilməz”;
  • backpressure: “növbədə 100‑dən çox yerinə yetirilməmiş tapşırıq ola bilməz, əks halda yeni sorğulardan imtina edirik”.

İdealda bu mexanizmlər bir‑birini tamamlayır: rate limit müştəriləri cilovlayır, backpressure isə hər halda çox adam yüklənəndə sistemi xilas edir.

Aktiv tapşırıqların məhdudlaşdırılmasının sadə reallaşdırılması

Backpressure‑ın ən sadə variantlarından biri — daxildə aktiv çağırışların sayını məhdudlaşdırmaqdır. Məsələn: konkret backend/REST xidmətinə (Gift API, Commerce API və s.) eyni vaxtda 50‑dən çox aktiv tool‑call saxlamamaq.

let activeCalls = 0;
const MAX_ACTIVE = 50;

app.post("/mcp/tools/call", async (req, res) => {
    if (activeCalls >= MAX_ACTIVE) {
        return res.status(429).json({
            error: "gateway_overloaded",
            message: "Gateway is temporarily overloaded, please retry later."
        });
    }

    activeCalls += 1;
    try {
        const result = await callBackendForTool(req.body); // Gift/Commerce/Analytics API‑yə REST çağırışı
        res.json(result);
    } catch (err) {
        console.error("Tool call error", err);
        res.status(500).json({ error: "internal_error" });
    } finally {
        activeCalls -= 1;
    }
});

Burada nə baş verir:

  • eyni vaxtda icra olunan sorğuların sayı MAX_ACTIVE‑dən az olduğu müddətdə, yeni call‑u buraxırıq;
  • limit bitibsə, dərhal məzmunlu səhv qaytarırıq;
  • mütləq finally içində sayğacı azaltmaq vacibdir ki, xətalarda “slotlar” itirilməsin.

Bu, ən sadə backpressure‑dır: müştəriyə dürüstcə deyirik: “indi bacarmıram, biraz sonra yoxla”, hər şeyi düşünmədən qəbul edib ölmək əvəzinə.

Sonradan aşağıdakıları etmək olar:

  • fərqli əməliyyat tipləri üçün müxtəlif MAX_ACTIVE dəyərləri (məsələn, checkout‑u demək olar ki, həmişə buraxmaq, hesabat generasiyasını isə daha sərt məhdudlaşdırmaq),
  • yük metriklərinə əsasən limitləri dinamik dəyişmək.

7. Webhook‑lar və “fırtınalar”: daxil olan hadisələrin müdafiəsi

Buraya qədər əsasən bizim və ya ChatGPT‑nin (tool‑call‑lar, çıxan sorğular, async‑job‑lar) başlatdığı sorğulara baxdıq. Amma həyatda Gateway üçün daha bir önəmli yüklənmə mənbəyi var — xarici sistemlərdən daxil olan webhook‑lar.

Webhook‑lar medalın digər üzüdür: tool‑call‑ları biz (model vasitəsilə) başladırıqsa, webhook‑ları xarici servis başladır. Bu, 4‑cü bölmədəki üçüncü trafik tipidir; zamanını və tezliyini biz idarə etmirik, amma yıxılmadan həzm etməliyik. Ödəniş, ACP, logistika — hamısı hər əhəmiyyətli dəyişikliyə görə bizim endpoint‑ə bildiriş (webhook) göndərir: “ödəniş keçdi”, “sifariş yaradıldı”, “çatdırılma statusu yeniləndi”.

Problemlər o zaman başlayır ki:

  • bizim endpoint yavaş cavab verir;
  • səhv cavab verir;
  • periodik əlçatmaz olur.

Bu halda, ən yaxşı təcrübələrə uyğun olaraq, xarici servis təkrar cəhdlər (retries) etməyə başlayır. Və bəxtiniz gətirməsə, webhook “fırtınası” alacaqsınız — istənilən qiymətə sizə “çatmağa” çalışan onlarla, hətta yüzlərlə təkrar hadisə.

Bundan ölməmək üçün, Gateway səviyyəsində belə edin:

  1. Daxil olan webhook‑ları mənbəyə görə limitləyin: məsələn, “konkret provayderdən bir event_type üçün dəqiqədə 10 hadisədən çox olmasın”.
  2. İmzaları JSON parsinqindən əvvəl yoxlayın: HMAC‑imza və ya oxşar mexanizm saxta sorğuları atmağa imkan verir.
  3. Hadisə emalını idemponent edin: event_id və ya oxşar sahə üzrə ki, təkrar hadisələr sifarişlərin və ya ödənişlərin dublikatına səbəb olmasın.
  4. Güclü fırtınada əlavə backpressure yandırın: downstream‑xidmətlər yetişmirsə, müvəqqəti olaraq “503: sonra yenə yoxlayın” cavabı verin.

Ən sadə nümunə (ideya, prodakşn kodu deyil):

app.post("/webhooks/stripe", rateLimitWebhook, (req, res) => {
    const sig = req.headers["stripe-signature"] as string;
    if (!isValidSignature(req.rawBody, sig)) {
        return res.status(400).send("Invalid signature");
    }

    const event = JSON.parse(req.body.toString());
    if (isAlreadyProcessed(event.id)) {
        return res.json({ received: true }); // idemponentlik
    }

    handleStripeEvent(event);
    res.json({ received: true });
});

Burada Gateway səviyyəsində biz:

  • webhook‑lar üçün ayrıca rate limiting siyasəti tətbiq edirik;
  • məzmununa etibar etməzdən əvvəl imzanı doğrulayırıq;
  • isAlreadyProcessed vasitəsilə dublikatlardan qorunuruq.

8. GiftGenius‑a tətbiq: limitlər və növbələr üçün siyasət nümunəsi

İndi isə abstraksiyalardan ayrılıb, bunu bizim tədris dəsti GiftGenius üçün necə görünə biləcəyinə baxaq.

Üç əsas ssenari təsəvvür edək:

  1. Hədiyyə axtarışı (suggest_gifts, find_similar_gifts).
  2. Sifarişin yaradılması / checkout (create_checkout_session, confirm_order).
  3. Daxil olan webhook‑lar ödəniş provayderindən və ACP‑dən.

Hər ssenari üçün məntiqli olanı müəyyənləşdirin:

  • limiti hansı açara görə hesablayırıq;
  • dəqiqədə neçə sorğuya icazə veririk;
  • hədd aşılarsa nə edirik.

Məsələn:

Ssenari Limit açarı Dəqiqədə limit Hədd aşılarsa davranış
Hədiyyə axtarışı userId 30 429 + məsləhət: “axtarış parametrlərini daraltmaq”
Sifarişin yaradılması userId + tenantId 5 429 + mətn: “çox cəhd etmisiniz, sifarişləri yoxlayın”
Daxil olan webhook‑lar provider + eventType 10 429/503, log, mümkün deqradasiya

Webhook‑lar üçün adətən “provayder + hadisə tipi” kombinasiyasına görə məhdudlaşdırmaq daha məntiqlidir, dublikatları isə event_id üzrə ayrıca idemponentlik mexanizmi ilə kəsmək lazımdır.

Koddakı qarşılığı — müxtəlif middleware‑lər: rateLimitSearch, rateLimitCheckout, rateLimitWebhook.

“İllik hədiyyə hesabatının böyük PDF‑ni yarat” kimi ağır əməliyyatlar üçün isə yuxarıda göstərdiyimiz növbə və asinxron paterndən istifadə edirik. Bu halda Gateway:

  • ChatGPT‑dən sorğunu qəbul edir;
  • tapşırığı növbəyə qoyur;
  • jobId və model üçün statusu necə almaq barədə ipucu qaytarır;
  • sistemi doldurmamaq üçün növbənin ölçüsünü (backpressure) məhdudlaşdırır.

Unutmayın: həm rate limiting, həm də backpressure — təkcə təhlükəsizlik və etibarlılıq yox, həm də UX məsələsidir. Asistentdən “Xidmət hazırda yüklüdür, gəlin bir dəqiqədən sonra yoxlayaq” eşitmək, taymauta qədər spinnerə baxmaqdan və ya “Internal Server Error” görməkdən qat‑qat xoşdur.

9. Mini‑praktikum: MCP Gateway‑imizə müdafiə əlavə edirik

Material nəzəriyyədə qalmasın deyə, tədris layihənizdə reallaşdıra biləcəyiniz mini‑praktikum yığaq.

Bütün MCP tool‑call‑lar üçün rate limiting

rateLimit middleware‑ini (yuxarıdakı kimi) əlavə edin və onu /mcp/tools/call‑a qoşun. Başlanğıc üçün çox sadə limit götürmək olar: userId üçün dəqiqədə 30 sorğu. Sonra oynayın:

  • limiti azaldın və App‑inizin və modelin buna necə reaksiya verdiyini izləyin;
  • məsələn, toolName‑i middleware‑ə ötürüb, fərqli tool tipləri üçün müxtəlif limitlər edin.

Aktiv çağırışlara görə ən sadə backpressure

activeCalls sayğacını və MAX_ACTIVE məhdudiyyətini əlavə edin. Yüklənməni imitasiya edin (məsələn, bir dəstə sorğu göndərən skriptlə) və Gateway‑in nə vaxt gateway_overloaded cavabı qaytardığını izləyin.

Burada vacib olan davranışdır: hər şeyin yıxılmasını gözləmir, əksinə yeni tapşırıqları almaqdan imtina edib, müştəriyə hal‑hazırda çox isti olduğunu dürüstcə deyirsiniz.

Ağır alət üçün növbə

Bir ağır əməliyyat seçin (və ya süni şəkildə “ağır” edin — setTimeout/uzun fetch daxil edin) və onu “növbə + jobId” paterni ilə keçirin. Minimum:

  • POST /mcp/tools/generate_report endpoint‑i — tapşırığı növbəyə qoyur və jobId qaytarır;
  • GET /jobs/:id endpoint‑i — statusu qaytarır (pending, done, error və bəlkə də nəticə);
  • processJob‑u X millisekunddan bir çağıran worker.

BullMQ və ya başqa queue mexanizmi ilə real inteqrasiyanın necə görünəcəyini anlamaq üçün bu kifayətdir.

10. Perimetr müdafiəsində tipik səhvlər

Səhv №1: Yalnız IP üzrə limitləmək.
ChatGPT Apps dünyasında bu demək olar ki, faydasızdır: sorğuların böyük hissəsi OpenAI ünvanlarından gəlir və bütün istifadəçiləriniz eyni IP arxasında olacaq. Nəticədə kimsə bir nəfər hamı üçün limiti yandıracaq, əsl günahkar isə məlum olmayacaq. Daha düzgünü userId, tenantId və ya tokenə görə limitləmək, IP‑ni isə yalnız tərs proxy səviyyəsində çox kobud filtr kimi istifadə etməkdir.

Səhv №2: Məzmunlu səhv əvəzinə çılpaq 500 qaytarmaq.
Limit aşılarkən və ya həddən artıq yüklənmədə sadəcə 500 Internal Server Error göndərsəniz, model heç nə başa düşmür və uydurmağa başlayır. Halbuki kodu olan strukturlaşdırılmış səhv (rate_limit_exceeded, gateway_overloaded) və insan üçün oxunaqlı izah LLM‑ə vəziyyəti düzgün izah etməyə və lazım gələrsə, bir az sonra yenidən cəhd etməyə imkan verir.

Səhv №3: Backpressure olmadan sonsuz növbə saxlamaq.
Bəzən elə gəlir: “hər şeyi növbəyə qoyaq, sonra baxarıq”. Praktikada növbə minlərlə tapşırığa qədər böyüyür, gecikmələr artır, yaddaş bitir, istifadəçi isə nəticəni görmür. Növbənin ölçüsünü və aktiv əməliyyatların sayını hər zaman məhdudlaşdırın. 503 və ya 429 ilə yeni sorğulardan dürüst imtina etmək, növbəni “qara dəliyə” çevirməkdən yaxşıdır.

Səhv №4: Yalnız rate limiting‑ə arxalanmaq və webhook‑ları görməməzliyə vurmaq.
Çoxları yalnız ChatGPT‑dən gələn daxil olan trafiki qoruyur, webhook‑ları isə “öz‑özünə nəsə olar” kimi saxlayır. Ödəniş provayderi təkrar cəhdlər etməyə başlayanda, məhz webhook‑lar sizə əsl fırtına qura bilər. Webhook endpoint‑ləri üçün ayrıca limitlər, imza yoxlaması və idemponent emal lazımdır. Əks halda eyni sifarişin onlarla dublikatını almaq çox asandır.

Səhv №5: Bütün sayğacları və növbəni tək instansın yaddaşında saxlamaq.
Tədris layihəsi üçün normaldır, amma prodakşnda Gateway bir neçə instansa şaxələnəndə hər node‑dakı sayğaclar “öz həyatını yaşayacaq”, limitlər qlobal olmayacaq, node yenidən başladıqda isə növbə sıfırlanacaq. Real sistemdə limit və növbə vəziyyəti üçün ümumi saxlama istifadə olunur (Redis, bulud növbələri və s.). Bu mövzuya miqyaslandırma və prodakşn dərslərində yenə qayıdacağıq.

Səhv №6: “Onsuz da hər yerdə vasitəçidir” deyib, biznes məntiqini Gateway‑in içinə soxmaq.
Bəzən cazibə yaranır: “gəlin elə Gateway‑də qərar verək, hansı hədiyyələri göstərək, axır onsuz da ora sorğular gəlir”. Nəticədə gateway bir dəstə məntiqə sahib monolitə çevrilir: həm marşrutlayıcı, həm biznes beyni, həm də loqqer. Bu, miqyaslandırma və dəstəkləməni xeyli çətinləşdirir. Gateway şəbəkə/infrastruktur qatı olaraq qalmalıdır: autentifikasiya, avtorizasiya, limitlər, keş, marşrutlaşdırma — bəli; hədiyyə seçimi — xeyr.

Səhv №7: “Biz kiçiyik, bu bizi maraqlandırmır” düşünmək.
Çoxları belə düşünür: “Axı bizdə milyonlarla istifadəçi yoxdur, gateway/limitlərsiz də keçinərik”. Əslində isə müştəri kodunda bir xəta (və ya modeli tool‑u dairəvi çağırmağa sövq edən prompt) sizə kiçik, amma lokal apokalipsis qura bilər. Baza rate limiting və heç olmasa primitiv backpressure — lüks deyil, prodakşnın diş fırçasıdır: xəstəlik başlamadan, elə əvvəldən istifadə etmək lazımdır.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION