200 OK bez żadnej treści, stream urywa się w połowie
wywołania narzędzia. Ta strona to kontrakt dla takich przypadków: co dostaje
wywołujący, czy GoModel ponawia request lub robi failover i gdzie zdarzenie pojawia
się w Twoim monitoringu.
Ustawienia sterujące retry i circuit breakerem opisuje strona
Odporność na awarie. Wybór modelu zapasowego opisuje strona
Failover.
Schema drift
Zmiana kształtu odpowiedzi przez providera to awaria, o której gatewaye zwykle milczą, bo odpowiedź na nią wymaga opinii, jak odpowiedź powinna wyglądać. Opinią GoModel jest schemat OpenAI, stosowany wyrozumiale: nieznane pola przetrwają, znane pola są normalizowane, a tylko odpowiedź, której nie da się w ogóle odczytać, staje się błędem.
Endpointy passthrough są z tego wszystkiego wyłączone:
/p/{provider}/... przekazuje
bajty od providera bez stosowania opinii GoModel, więc klient, który
woli sam radzić sobie z dryfem schematu, może to zrobić.
Puste odpowiedzi wyglądające na udane
200 bez użytecznej treści to awaria przebrana za sukces. Pytanie
brzmi, czy warto robić na niej failover – a w przypadku chat completions
odpowiedź brzmi: tak.
Każdy wiersz loguje ostrzeżenie ze wskazaniem providera, modelu i przyczyny oraz
zwiększa
gomodel_empty_responses_total. Ponieważ gomodel_requests_total
liczy dostarczone wiersze jako sukcesy, ten licznik jest jedynym miejscem, w którym
pojawiają się wiersze bez błędu.
Wywołanie
/v1/responses w tle lub w toku z założenia nie zawiera
ani output, ani usage i nigdy nie jest raportowane jako puste.Awarie streamingu
Streamu, który już wysłał bajty, nie da się ponowić – klient ma część odpowiedzi. Dlatego reguła GoModel brzmi: decyduj przed pierwszym bajtem, tam gdzie to możliwe, i jawnie sygnalizuj przerwanie tam, gdzie nie jest.
Oczekiwanie na pierwszy bajt nigdy nie wlicza się do idle timeoutu, więc wolny
model reasoning jest bezpieczny, dopóki provider czegoś nie wyśle. Potem każdy
bajt uruchamia licznik czasu – łącznie z komentarzem keep-alive – a każdy kolejny bajt
go restartuje, więc limit ogranicza przerwę między odczytami, a nie długość
odpowiedzi. Gdy pierwszy bajt zostanie wysłany, odpowiedź jest zatwierdzona jako
200, dlatego zawieszenie od tego momentu można zgłosić tylko w paśmie,
a nigdy jako status. Szczegóły:
zakończenie streamu,
idle timeout,
failover na starcie streamu.
Awarie transportu i statusów
Konwencjonalne przypadki, dla kompletności.
Requesty streamingowe nigdy nie są ponawiane po wysłaniu, a requesty passthrough
tylko wtedy, gdy ponowienie jest bezpieczne (
GET, HEAD, OPTIONS, PUT lub dowolny
request z Idempotency-Key).
Wyłapywanie cichych awarii
Wiersze powyżej, które nie uruchamiają failoveru, wymagają alertu, bo z definicji nic innego nie zgłasza problemu:gomodel.client.empty_responses,
gdzie przyczyna trafia jako error.type, a nie reason, obok
gomodel.provider.name i gen_ai.request.model. Zobacz
Metryki Prometheus i
OpenTelemetry.
Dashboard odczytuje te same sygnały: model, którego ostatnie requesty ciągle
kończą się błędem, oznacza swojego providera jako Degraded, nawet gdy wykrywanie modeli nadal
działa – to właśnie wyłapuje upstream, który poprawnie listuje modele, ale zawodzi
przy prawdziwych wywołaniach.
Awarie wykrywania modeli
Lista/models providera może przestać działać, podczas gdy inferencja nadal działa. GoModel
kontynuuje routing, korzystając kolejno z:
- Ostatniego inwentarza, który pobrał lub załadował ze swojego cache’u.
- Skonfigurowanych modeli (
<PROVIDER>_MODELS, zobaczCONFIGURED_PROVIDER_MODELS_MODE). - Dla providera na domyślnym bazowym URL – listy z katalogu modeli dla jego typu providera.
PROVIDER_RECHECK_INTERVAL sekund
(domyślnie 60), a aktualna lista zastępuje zastępczą, gdy tylko listowanie
się powiedzie. Gdy nie ma czego serwować, requesty zwracają 503, aby klienci ponowili próbę,
a /health/ready raportuje degraded z "models": "down", podczas gdy instancja
pozostaje w rotacji.
Aby nigdy nie zależeć od wykrywania, wypisz modele samodzielnie i ustaw
CONFIGURED_PROVIDER_MODELS_MODE=allowlist:
Gdy nie działa sam GoModel
Umieszczenie gatewaya na ścieżce requestu zamienia ryzyko providera na ryzyko gatewaya, więc uczciwe liczby są ważniejsze niż zapewnienia. GoModel zawodzi głośno, a nie po cichu: martwa instancja daje odmowę połączenia lub502 od tego, co stoi przed nią, a nigdy wiarygodnie wyglądającą błędną odpowiedź.
To jeden statyczny plik binarny z bezstanową ścieżką requestu, probe’ami /health i
/health/ready oraz 10-sekundowym łagodnym wygaszaniem (graceful drain) po SIGTERM, więc
restarty kroczące i wiele replik za load balancerem działają już dziś.
To wygaszanie jest odcięciem, a nie gwarancją dokończenia: jest dobrane do
requestów, które faktycznie mogą się zakończyć w dziesięć sekund, a wszystko, co nadal jest otwarte
po tym czasie – przede wszystkim trwający stream – ma zrywane połączenie. Dla
długotrwałego ruchu wygaszaj połączenia na load balancerze, utrzymuj nakładające się repliki
wystarczająco długo, by objąć czas generowania, i pozwól klientom ponawiać requesty.
Co jest per instancja, a więc nie jest współdzielone między replikami: stan circuit
breakera, liczniki rate limitów, okna stanu requestów i sticky
sessions. Przewodnik produkcyjny opisuje, co to oznacza
dla Twojej topologii.
Jeśli GoModel nie działa, a ruch musi płynąć natychmiast, skieruj
base_url z powrotem bezpośrednio na providera – API jest kompatybilne z OpenAI w
obu kierunkach. Dopóki GoModel nie wróci, tracisz routing, failover i logowanie –
a ponieważ działają one na ścieżce requestu GoModel, a nie
providera, jego rate limity i kontrole budżetu przestają cokolwiek blokować.