Skip to main content
Providerzy psują się na sposoby, które nie są awariami. Pole zmienia typ po cichym wdrożeniu, przychodzi 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.
Na wiersz ze znikającym polem warto ustawić alert. To nie jest incydent – to liczba, która po cichu maleje, a nikt jej nie szuka. Zobacz Wyłapywanie cichych awarii poniżej.
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:
Oba są eksportowane przez OpenTelemetry jako 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:
  1. Ostatniego inwentarza, który pobrał lub załadował ze swojego cache’u.
  2. Skonfigurowanych modeli (<PROVIDER>_MODELS, zobacz CONFIGURED_PROVIDER_MODELS_MODE).
  3. Dla providera na domyślnym bazowym URL – listy z katalogu modeli dla jego typu providera.
Providerzy z błędem są ponownie sprawdzani co 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 lub 502 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ć.
Ostatnia modyfikacja 24 października 2026