Программно определить, завис ли локальный веб-сервер

Я понимаю, что получу по крайней мере один ответ в духе "(переписать) код, чтобы он не зависал", но давайте предположим, что мы еще не живем в этой блестящей счастливой утопии…

В нашей встроенной системе у нас есть большой SDK, включающий веб-сервер (Boa), который является основным методом взаимодействия с пользователем.

Возможно, на определенных фазах луны что- то может привести к зависанию веб-сервера или его застреванию таким образом, что процесс будет работать нормально (не сбоит / не работает / использует 100% ЦП), но не будет обслуживать веб-сайты. страницы

Итак, вопрос в том, как мы можем проверить / обнаружить эту ситуацию?

1 ответ

Решение

Чтобы проверить, завис ли сервер, создайте сокет TCP и подключитесь к порту. 80 по IP адресу 127.0.0.1 (адрес обратной связи). Затем отправьте следующий текст через сокет

GET / HTTP/1.1\r\n\r\n

Большинство серверов будут интерпретировать это как запрос index.html, В качестве альтернативы, вы можете реализовать недокументированный URL для тестирования (что позволяет получить более короткий, заранее определенный ответ), например

GET /test/fdoaoqfaf12491r2h1rfda HTTP/1.1\r\n\r\n

Затем вам нужно прочитать ответ с сервера. Это предполагает использование select с разумным временем ожидания, чтобы определить, возвращались ли какие-либо данные с сервера, и если да, используйте recv читать данные. Ответ от сервера будет состоять из заголовка и контента. Заголовок состоит из строк текста, с пустой строкой в ​​конце заголовка. Строки заканчиваются \r\n так что конец заголовка \r\n\r\n,

Получение контента включает в себя звонки select а также recv до тех пор recv возвращает 0. Предполагается, что сервер отправит ответ, а затем закроет сокет. Некоторые сложные серверы оставляют сокет открытым, чтобы разрешить несколько запросов через один сокет. Простой встроенный сервер не должен этого делать. (Если ваш сервер пытается использовать один и тот же сокет для нескольких запросов, вам необходимо выяснить, как отключить эту функцию.)


Это все очень хорошо, но вам действительно нужно переписать свой код, чтобы он не зависал.

Наиболее вероятная причина проблемы заключается в том, что на сервере имеется множество висячих сокетов, то есть соединений от клиентов, которые никогда не были должным образом очищены. Повисшие сокеты в конечном итоге не позволят серверу принимать больше соединений, либо потому, что сервер имеет ограничение на количество открытых соединений, либо потому, что процесс, на котором работает сервер, использует все свои файловые дескрипторы.

Первое, что нужно проверить, это значение таймаута TCP. Один проект, над которым я работал, имел время ожидания по умолчанию 5 часов, что означало, что висящие сокеты оставались открытыми в течение 5 часов. Разумное время ожидания составляет 1 минуту.

Тогда вам нужно создать клиента, который намеренно плохо себя ведет. Клиенты могут плохо себя вести

  • оставив сокет открытым без чтения ответа сервера
  • резко закрывая сокет во время чтения ответа
  • изящно закрывая сокет, читая ответ

Первая ситуация должна быть обработана таймаутом TCP. Два других должны быть правильно обработаны кодом сервера. Изящное и резкое закрытие сокета контролируется с помощью опции SO_LINGER ioctl и shutdown функция. После неправильного поведения клиента проверьте количество дескрипторов открытых файлов в процессе сервера, чтобы убедиться, что сервер правильно обработал ситуацию.

Другие вопросы по тегам