Nie mogę znaleźć cytatu w dokumentacji, ale moje doświadczenie sugeruje, że ogólnie infrastruktura sieciowa EC2 (która obejmowałaby RDS i prawdopodobnie każdą inną usługę AWS działającą na maszynach wirtualnych, które są udostępniane na klienta, jeśli nie wszystkie AWS i na pewno nie wydaje się być ograniczony wyłącznie do „instancji EC2”) implementuje stanową inspekcję pakietów i „zapomnie”, że połączenie TCP jest prawidłowe po kilku minutach absolutnej bezczynności… powodując opisane przez Ciebie zachowanie.
Maszyny na obu końcach połączenia mogą być przekonane, że połączenie nadal istnieje, ale sieć nie pozwoli na przepływ ruchu między nimi, ponieważ sesje TCP w środowisku SPI nie są wykrywane, są tworzone i mogą tylko być tworzone, gdy sieć zobaczy połączenie na samym początku (SYN, SYN/POTW, POTW ). Początkowo napotkałem ten problem z serwerami MySQL w EC2 (nie RDS), ale byłbym bardzo zaskoczony, gdyby podstawowa przyczyna nie była taka sama.
Istnieją dwa możliwe sposoby obejścia tego problemu.
Jeśli twoją maszyną PHP jest Linux, skonfiguruj jądro tak, aby połączenia były aktywne w warstwie 4. Ta zmiana będzie dla ciebie niewidoczna w tym sensie, że te podtrzymania nie zmienią wartości w Time
kolumna w SHOW PROCESSLIST
dla połączeń w Sleep
ponieważ nie zresetuje czasu, przez jaki połączenie było bezczynne w warstwie 7 ... ale powinno unikać przekroczenia limitów czasu z infrastruktury AWS, jeśli biblioteki zarządzające połączeniami MySQL ustawiają opcje gniazd poprawnie, aby z nich skorzystać.
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive .html wyjaśnia, jak skonfigurować to na żywo i jak sprawić, by było trwałe po ponownym uruchomieniu.
Jeśli to się nie uda, inną opcją jest wymuszenie zamknięcia połączenia przez MySQL wcześniej niż przekroczenie limitu czasu sieci aby maszyna PHP natychmiast rozpoznała, że próbuje rozmawiać na zamkniętym gnieździe. Skrócenie czasu oczekiwania zamiast wydłużania go może wydawać się sprzeczne z intuicją, ale skrócenie czasu oczekiwania powinno spowodować, że test ping zakończy się bardzo szybko, jeśli sesja była zbyt długo bezczynna, co również (zasadniczo) „rozwiązuje” problem, zakładając zdrowie psychiczne w bibliotece klienta PHP. Gdy aplikacja jest bardziej zajęta, połączenia prawdopodobnie rzadko będą bezczynne wystarczająco długo, aby osiągnąć limit czasu.
MySQL Server ma dwa różne ustawienia limitu czasu bezczynności: wait_timeout
(dla sesji nieinteraktywnych, tj. połączeń z kodu, takich jak PHP) i interactive_timeout
(z przeglądarek zapytań i klienta wiersza poleceń), ale serwer zna różnicę tylko dlatego, że biblioteka klienta musi powiadomić serwer, jaki rodzaj połączenia nawiązuje. Zakładając, że twoja biblioteka klienta używa prawidłowej konfiguracji, wtedy wait_timeout
jest tym, którego szukasz. Ustawienie tego na wartość poniżej 900 powinno rozwiązać problem, jeśli zmiana ustawień TCP utrzymywania aktywności w jądrze Linuksa nie rozwiąże problemu. Należy jednak pamiętać, że po wprowadzeniu zmiany wpłynie to tylko na przyszłe połączenia — połączenia już nawiązane podczas wprowadzania zmiany będą nadal działać z bieżącą wartością, która domyślnie wynosi 8 godzin (28800 sekund). Można je skonfigurować w grupie parametrów RDS dla Twojej instancji.
W dokumentacji AWS znajdują się wskazówki dotyczące podobnego zachowania , wraz z ustawieniami rejestru systemu Windows, które należy dostosować, aby zmienić utrzymywanie aktywności TCP, jeśli używasz serwera PHP w systemie Windows, a nie w systemie Linux, jak założyłem powyżej ... mimo że artykuł dotyczy konkretnie Redshift i połączeń zewnętrznych EC2 nadal wydaje się potwierdzać podstawową kwestię, jak omówiono powyżej.