ERR_HTTP2_PROTOCOL_ERROR: przyczyny i naprawa
ERR_HTTP2_PROTOCOL_ERROR oznacza, że przeglądarka i serwer pomyślnie wynegocjowały HTTP/2, ale konkretna ramka albo strumień w wymianie złamały reguły protokołu i połączenie zostało zresetowane. To co innego niż awaria TLS: zaszyfrowane połączenie zadziałało, a problem siedzi jedną warstwę wyżej, w tym, jak sam strumień HTTP/2 został uformowany.
Co oznacza ERR_HTTP2_PROTOCOL_ERROR
HTTP/2 wysyła żądania i odpowiedzi jako binarne ramki przez jedno połączenie, z restrykcyjnymi regułami dotyczącymi rozmiaru ramki, kodowania nagłówków (HPACK) i stanu strumienia. Serwer, proxy albo CDN, który wyśle wadliwą ramkę, zbyt duży nagłówek albo ramkę dla strumienia, który jest już zamknięty, łamie te reguły, a klient zamyka połączenie zamiast zgadywać, o co chodziło. Ponieważ awaria może pochodzić z serwera aplikacji, pośredniczącego proxy, brzegu CDN albo własnego stosu sieciowego przeglądarki, ten błąd obejmuje szerszy zakres pierwotnych przyczyn niż większość innych z tej listy.
Jak pojawia się błąd
Chrome i Edge pokazują "This page isn't working - ERR_HTTP2_PROTOCOL_ERROR", czasem tylko przy niektórych wczytaniach strony, a nie przy innych, co jest wskazówką, że wina jest sporadyczna, a nie stałą złą konfiguracją. Firefox zwykle pokazuje ogólny błąd połączenia zamiast nazwać protokół.
curl może wymusić HTTP/2 i pokazać dokładnie, na której ramce zawiodło połączenie:
curl --http2 -v https://example.com/ 2>&1 | tail -20
...
* Recv failure: Connection reset by peer
* HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
Porównanie tego z żądaniem HTTP/1.1 do tego samego URL izoluje, czy problem jest specyficzny dla protokołu:
curl --http1.1 -sI https://example.com/
Jeśli żądanie HTTP/1.1 się powiedzie, a HTTP/2 zawodzi, wina leży w tym, jak coś w łańcuchu implementuje HTTP/2, nie w samej aplikacji.
Co powoduje ERR_HTTP2_PROTOCOL_ERROR
- Wadliwe albo zbyt duże nagłówki z aplikacji albo proxy. Bardzo długie ciasteczko, zbyt duży zestaw nagłówków odpowiedzi albo wartość nagłówka zawierająca znaki, których HPACK nie może zakodować, naruszą rozmiar ramki oczekiwany przez serwer albo klienta.
- Reverse proxy albo load balancer z wadliwą albo przestarzałą implementacją HTTP/2. Niektóre starsze stosy HTTP/2 nginx, Apache albo urządzeń wbudowanych mają znane problemy z konkretnymi sekwencjami ramek pod obciążeniem.
- Błąd na brzegu CDN albo niedopasowanie protokołu między brzegiem a serwerem źródłowym. Odcinek przeglądarka-brzeg i odcinek brzeg-serwer źródłowy mogą używać różnych protokołów; błąd w tłumaczeniu między nimi czasem produkuje ten błąd tylko dla określonych kształtów żądania.
- Oprogramowanie antywirusowe albo rozszerzenie przeglądarki przechwytujące ruch HTTPS. Ta sama klasa oprogramowania, która powoduje awarie handshake'u SSL, może też złamać zdrowy strumień HTTP/2, jeśli jego warstwa przechwytywania nie mówi poprawnie HTTP/2.
- Nieaktualna przeglądarka ze starą implementacją HTTP/2, albo uszkodzony cache sieciowy przeglądarki.
- Niedopasowanie
Content-Lengthza reverse proxy. Jeśli nginx (albo inne proxy) przekazuje odpowiedź, której zadeklarowanyContent-Lengthnie zgadza się z rzeczywiście wysłanymi bajtami, framing HTTP/2 dalej w łańcuchu może się załamać w połowie.
Jak rozpoznać, kto zawinił
Uruchom kontrolę HTTP z kilku lokalizacji: jeśli awaria jest spójna wszędzie, winna jest obsługa HTTP/2 przez serwer albo CDN. Jeśli zawodzi tylko u Ciebie, dużo bardziej prawdopodobne jest, że przyczyna jest lokalna: przeglądarka, antywirus albo urządzenie sieciowe między Tobą a witryną.
Jak naprawić ERR_HTTP2_PROTOCOL_ERROR
Jeśli jesteś odwiedzającym
- Przeładuj stronę. Skoro przyczyną jest często pojedyncza wadliwa ramka, a nie trwała zła konfiguracja, świeże połączenie często się udaje.
- Wyczyść cache przeglądarki pod
chrome://settings/clearBrowserData, bo uszkodzony zbuforowany zasób może wywołać to przy przeładowaniu. - Wyłącz tymczasowo skanowanie HTTPS/SSL antywirusa i spróbuj ponownie; ta klasa oprogramowania to częsta i często pomijana przyczyna.
- Wypróbuj okno incognito, żeby wykluczyć rozszerzenie.
- Zaktualizuj przeglądarkę do najnowszej wersji, bo starsze implementacje klienta HTTP/2 miały znane błędy.
Jeśli prowadzisz witrynę
- Porównaj HTTP/2 z HTTP/1.1 powyższymi poleceniami curl. Jeśli zawodzi tylko HTTP/2, problem leży w warstwie HTTP/2 proxy albo CDN, nie w aplikacji.
- Podnieś limity rozmiaru nagłówków nginx, jeśli zaangażowane są duże ciasteczka albo nagłówki:
Zrestartuj albo przeładuj nginx po zmianie i przetestuj ponownie.http2_max_field_size 16k; http2_max_header_size 32k; large_client_header_buffers 4 16k; - Sprawdź niedopasowanie
Content-Lengthmiędzy tym, co wysyła aplikacja, a tym, co przekazuje proxy; włącz buforowanie proxy (proxy_buffering on;), żeby nginx mógł przeczytać całą odpowiedź, zanim opakuje ją w ramki HTTP/2. - Zaktualizuj nginx, Apache albo dowolny load balancer do aktualnej wersji; błędy obsługi ramek HTTP/2 to dokładnie ten typ rzeczy, który naprawiają wydania punktowe.
- Wyłącz HTTP/2 jako test diagnostyczny, nie stałą naprawę: usuń tymczasowo
http2z dyrektywylistennginx. Jeśli błędy ustają, potwierdzone jest, że wina leży konkretnie w warstwie HTTP/2, i możesz ponownie ją włączyć, gdy powyższa naprawa nagłówków albo buforowania będzie wdrożona. - Sprawdź logi po stronie CDN, jeśli jakiś stoi przed serwerem źródłowym; większość CDN-ów ujawnia błędy framingu HTTP/2 w swoich logach brzegowych z większą szczegółowością, niż kiedykolwiek pokaże przeglądarka.
Powiązane błędy
- ERR_SSL_PROTOCOL_ERROR wygląda podobnie, ale zawodzi wcześniej, podczas handshake'u TLS, zanim jakakolwiek ramka HTTP/2 zostanie w ogóle wymieniona.
- Kody błędów serwera 5xx obejmują przypadki, w których połączenie i protokół działają dobrze, ale zawodzi sama aplikacja.
Warto oddzielić jeden szczegół: błąd protokołu HTTP/2 to nie to samo co strumień HTTP/2 czysto zresetowany przez aplikację, na przykład gdy klient anuluje żądanie w trakcie lotu. Narzędzia deweloperskie przeglądarki i logi dostępu serwera czasem oznaczają oba przypadki jako "reset", ale tylko prawdziwe naruszenie framingu produkuje ERR_HTTP2_PROTOCOL_ERROR w przeglądarce; celowo anulowany strumień po prostu się zatrzymuje, bez strony błędu.
Jak zapobiec ERR_HTTP2_PROTOCOL_ERROR
Ponieważ ten błąd jest często sporadyczny, powiązany z konkretnymi rozmiarami nagłówków albo konkretnymi wersjami proxy, może dotykać części odwiedzających przez tygodnie, zanim ktokolwiek zauważy wzorzec. Kontrola HTTP działająca według harmonogramu z wielu lokalizacji wyłapuje rosnący wskaźnik awarii zaraz po wdrożeniu, zmianie CDN albo aktualizacji proxy, zamiast polegać na rozproszonych zgłoszeniach użytkowników. HostTracker alarmuje e-mailem, SMS-em, połączeniem głosowym, przez Slack, Telegram i inne kanały, gdy tylko kontrola zaczyna zawodzić.
Najczęściej zadawane pytania
Czy ERR_HTTP2_PROTOCOL_ERROR to to samo co błąd SSL?
Nie. Ten błąd zdarza się po udanym TLS, na warstwie framingu HTTP/2. Błąd SSL oznacza, że samo zaszyfrowane połączenie nigdy się nie uformowało.
Dlaczego błąd pojawia się tylko czasem, nie przy każdym wczytaniu strony?
Większość przyczyn tutaj jest wywoływana przez konkretne warunki, nagłówek, który urósł powyżej limitu, wyścig w proxy pod obciążeniem, konkretny zbuforowany zasób, a nie przez stałą złą konfigurację, która zawodzi za każdym razem.
Czy wyłączenie HTTP/2 na moim serwerze pogorszy wydajność?
HTTP/2 oferuje realne korzyści (multipleksowanie, kompresję nagłówków), więc traktuj wyłączenie go jako tymczasowy krok diagnostyczny, nie stałą naprawę. Napraw leżący u podstaw problem z rozmiarem nagłówków albo buforowaniem i włącz je ponownie.
Czy CDN może to spowodować, nawet jeśli mój serwer źródłowy jest w porządku?
Tak. Brzeg CDN i serwer źródłowy mogą używać różnych protokołów na każdym odcinku połączenia, a błąd albo zła konfiguracja w sposobie, w jaki CDN tłumaczy między nimi, może wyprodukować ten błąd niezależnie od kondycji samego serwera źródłowego.
Czy zdarza się to na witrynach HTTP/1.1?
Nie, ERR_HTTP2_PROTOCOL_ERROR jest specyficzny dla połączeń, które wynegocjowały HTTP/2. Witryna serwująca wyłącznie HTTP/1.1 nie może wyprodukować akurat tego błędu, choć może mieć własne problemy z połączeniem.