Ograniczaliśmy sami nasze własne usługi
API Mythex pozwala na 300 żądań na minutę z jednego adresu sieciowego. Ten limit chroni nas przed pojedynczą osobą albo skryptem, który zasypuje API zapytaniami. Na produkcji zaczął jednak odrzucać nasze własne usługi — część brzegową, która obsługuje opublikowane aplikacje, i usługę uruchamiającą agenta AI — bo każda z nich łączy się z API tylko z garstki adresów. Żądania z naszym wewnętrznym poświadczeniem są teraz zwolnione z limitu, a wszyscy inni są ograniczani dokładnie tak jak wcześniej.
Objaw
API zaczęło odpowiadać części naszych wewnętrznych wywołań kodem 429 Too Many Requests. Dotknęły trzy rodzaje wywołań, a każdy z nich ma znaczenie dla kogoś, kto używa Mythex:
- Sprawdzanie, która aplikacja mieszka pod własną domeną. Gdy odwiedzający otwiera opublikowaną aplikację pod jej własną domeną, nasz edge pyta API, gdzie jest ta strona. 429 w tym miejscu oznacza odwiedzającego, który nie może dotrzeć do strony.
- Zapisywanie trwającej tury agenta. Gdy agent pracuje, jego postęp zapisuje się na bieżąco, żeby odpowiedź przetrwała odświeżenie albo zerwane połączenie. 429 w tym miejscu oznacza postęp, który nie został zapisany.
- Sprawdzanie dostępu do podglądu. Podgląd aplikacji, którą budujesz, jest zabezpieczony, a zabezpieczenie pyta API. 429 w tym miejscu oznacza podgląd, który się nie otworzy.
Żadne z tych wywołań nie pochodziło od ludzi korzystających z API. Wszystkie pochodziły od nas.
Dlaczego tak się stało
Limit na adres zakłada jedną rzecz: jeden adres to z grubsza jeden wywołujący. Dla ludzi to wystarczająco blisko. Dla naszej własnej infrastruktury jest to bardzo złe założenie.
- Usługa brzegowa, która obsługuje opublikowane aplikacje i podglądy, łączy się z API z kilku współdzielonych adresów wychodzących. Każdy odwiedzający każdą opublikowaną aplikację i każde sprawdzenie podglądu przychodzi jako jeden z tych kilku.
- Orkiestrator — usługa uruchamiająca tury agenta — łączy się z API z jednego adresu kontenera. Każda działająca tura, dla każdego użytkownika, dzieli ten adres.
Budżet przeznaczony dla jednej osoby był więc dzielony między cały ruch całej usługi. Te usługi zużyły go razem, a limiter zrobił to, do czego był przeznaczony: odmówił im.
Naprawa
Nasze własne usługi już potwierdzają, kim są. Każde wewnętrzne wywołanie niesie wewnętrzny token, a każda trasa w wewnętrznej części API sprawdza ten token, zanim cokolwiek zrobi.
Limiter używa teraz tego samego sprawdzenia. Żądanie, którego token pasuje do wewnętrznego, trafia na listę dozwolonych i nie jest liczone w budżecie na adres. Wszystko inne liczy się dokładnie jak wcześniej: 300 żądań na minutę na adres.
Dwa szczegóły nie pozwoliły, by z tego zrobiła się dziura:
- Zły token nie daje przepustki. Lista dozwolonych pasuje tylko do prawdziwego wewnętrznego tokenu. Żądanie z wymyślonym tokenem jest liczone i ograniczane jak każde inne, a wewnętrzne trasy i tak odrzucają je z
401 Unauthorized. - Sam limit się nie zmienił. Nie podnieśliśmy liczby, żeby zrobić miejsce. Podniesienie ukryłoby problem tylko do chwili, gdy ruch znów urośnie, i osłabiłoby ochronę w przypadku, dla którego limit istnieje.
Przenieśliśmy ustawienia limitera do jednej małej funkcji i napisaliśmy do niej testy. Jeden wysyła 20 żądań z wewnętrznym tokenem do limitera ustawionego na 5 i oczekuje, że wszystkie 20 się powiedzie. Inny wysyła zwykłe żądania z jednego adresu i oczekuje, że pierwsze pięć się powiedzie, a kolejne zostaną odrzucone. Trzeci wysyła żądania z podrobionym tokenem i oczekuje, że zostaną odrzucone w ten sam sposób.
Co z tego wynieśliśmy
- Limity niosą założenia. „Jeden adres, jeden wywołujący” jest wbudowane w limit na adres. Przestaje być prawdziwe, gdy Twoje własne usługi stoją za współdzielonymi adresami — a wiele ich stoi: load balancery, sieci brzegowe, kontenery, sieci biurowe.
- Rozróżniaj swój ruch po tożsamości, a nie po adresie. Adresy opisują, jak ruch przychodzi, a nie kto go wysłał. Mieliśmy już poświadczenie, które dowodzi, że wywołanie jest nasze; limiter po prostu na nie nie patrzył.
- Nie naprawiaj tego przez podniesienie liczby. Większy limit usunąłby 429 na jakiś czas, chronił mniej i zawiódł ponownie później.
- Patrz, kto jest ograniczany. 429, które trafia w Twoją własną usługę, to zgłoszenie błędu o Twoich limitach, a nie dowód, że limiter działa.
Co to oznacza, jeśli budujesz w Mythex
Nie musisz nic zmieniać po swojej stronie. Opublikowane aplikacje pod własnymi domenami, tury agenta i podglądy nie zależą już od tego, jak zajęty jest reszta Mythex. Ruch Twojej aplikacji to Twoja sprawa: opisany tu limit dotyczy naszego API, a nie aplikacji, które publikujesz.
Jeśli prowadzisz własny backend, ta sama pułapka dotyczy każdego limitu żądań, który dodasz. Nasze przewodniki czym jest API i lista kontrolna bezpieczeństwa dla aplikacji zbudowanych z AI to dobre miejsca na start. A po inny przykład, jak nasza własna infrastruktura przeszkadzała sama sobie, zobacz jak doprowadziliśmy wdrożenia do zera błędów 502.