Я пытаюсь сделать постоянное соединение с базой данных MySQL RDS от рабочего стола php, работающего на внешнем сервере ubuntu. В качестве части подключения я сначала проверяю «mysql_ping». Если ping возвращает true, используйте текущее соединение, иначе создайте новое соединение.
Проблема, с которой я столкнулся, заключается в том, что когда я начинаю свой рабочий, соединение устанавливает штраф и хорошо работает в течение некоторого времени, то есть я могу успешно выполнять повторные запросы к базе данных RDS. Однако примерно через 15 минут, если я сделаю запрос, тогда «mysql_ping» зависает, и, следовательно, сам скрипт php зависает. При дальнейшей отладке я обнаружил, что ответ mysql_ping вернулся после 936 секунд.
Необходимые разрешения для доступа к db с внешнего сервера есть и в течение всего этого времени (пока скрипт висит), я могу успешно подключиться к базе данных RDS с помощью параметров командной строки mysql. Кроме того, если я убью рабочего и снова его перезагружу, он сможет подключиться успешно еще раз, но проблема вернется через 15 минут или около того.
Есть ли что-то, что необходимо изменить в настройках сервера RDS, чтобы избежать этой проблемы?
С уважением, Капил
Я не могу найти ссылку в документации, но мой опыт показывает, что сетевая инфраструктура EC2 в целом (включая RDS и, возможно, любую другую услугу AWS, которая работает на виртуальных машинах, которые предоставляются каждому клиенту, если не все AWS и, конечно, не ограничивается строго «экземплярами EC2») реализует проверку пакетов с учетом состояния и будет «забывать» о том, что соединение TCP действительно после нескольких минут абсолютной безделья … вызывая поведение, которое вы описываете.
Машины на обоих концах соединения могут быть уверены, что соединение все еще существует, но сеть не позволяет трафику проходить между ними, поскольку сеансы TCP в среде SPI не обнаружены, они созданы и могут создаваться, когда сеть видит соединение в самом начале ( SYN, SYN / ACK, ACK ). Я первоначально столкнулся с этой проблемой с серверами MySQL в EC2 (не RDS), но был бы очень удивлен, если основная причина не такая.
Существует два возможных подхода к решению этой проблемы.
Если ваша PHP-машина – это Linux, настройте ядро, чтобы поддерживать соединения на уровне 4. Это изменение будет невидимым для вас в том смысле, что эти keepalives не изменят значение в столбце Time
в SHOW PROCESSLIST
для соединений в Sleep
потому что он не сбрасывает количество времени, в течение которого соединение простаивает на уровне 7 … но оно должно избегать тайм-аутов из инфраструктуры AWS, если библиотеки, управляющие соединениями MySQL, правильно устанавливают параметры сокета, чтобы воспользоваться им.
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html объясняет, как настроить это в прямом эфире, и как сделать его постоянным при перезагрузках.
В противном случае другой вариант заключается в том, чтобы заставить MySQL закрыть соединение раньше, чем сетевой тайм-аут, чтобы машина PHP сразу узнала, что пытается поговорить о закрытом сокете. Это может казаться противоречащим интуиции, чтобы сократить время ожидания, а не удлинять его, но сокращение таймаута должно привести к тому, что ваш тест ping завершится очень быстро, если сеанс слишком длительный, что также (по сути) «решает» проблему, предполагая здравомыслие в клиентской библиотеке PHP. Как только ваше приложение будет более занятым, соединения, по-видимому, редко будут простаивать достаточно долго, чтобы достичь таймаута.
MySQL Server имеет две разные настройки тайм-аута ожидания: wait_timeout
(для неинтерактивных сеансов, т. Е. Соединений из кода, например PHP) и interactive_timeout
(из браузеров запросов и клиента командной строки), но сервер знает только разницу, потому что клиентская библиотека имеет для уведомления сервера, какой тип соединения он устанавливает. Предполагая, что ваша клиентская библиотека использует правильную настройку, wait_timeout
– это тот, который вы ищете. Установка этого значения ниже 900 должна устранить проблему, если изменить настройки keepalive TCP в ядре Linux нет. Обратите внимание, однако, что после внесения изменений будут затронуты только будущие подключения – соединения, уже установленные при изменении, будут по-прежнему работать с текущим значением, которое по умолчанию составляет 8 часов (28800 секунд). Они настраиваются в группе параметров RDS для вашего экземпляра.
В документах AWS есть напоминания о подобном поведении , а также параметры реестра Windows, которые необходимо настроить для изменения TCP keepalives, если вы используете сервер PHP в Windows вместо Linux, как я предполагал выше … даже хотя в статье речь идет о Redshift и соединениях, внешних по отношению к EC2, по-прежнему, похоже, подтверждают основную проблему, как обсуждалось выше.