У меня проблема с клиент-серверным приложением. Поскольку у меня почти закончились вменяемые идеи по ее решению, я прошу помощи. Я сталкивался с описанной ситуацией три или четыре раза. Приведенные данные относятся к последнему сбою, когда я включил все возможные журналы, сброс сообщений и т. Д.
Описание системы
1) Клиент. Работает под Windows. Я предполагаю, что с его работой проблем нет (судя по логам)
2) Сервер. Работает под Linux (RHEL 5). Это сервер, на котором у меня проблема.
3) Между клиентом и сервером поддерживаются два соединения : одна команда и одна для отправки данных. Оба работают асинхронно. Оба соединения живут в одном потоке и в одном boost::asio::io_service
.
4) Данные для отправки от клиента к серверу - это сообщения, разделенные '\ 0'.
5) Загрузка данных составляет около 50 Мб / час, 24 часа в сутки.
6) Данные считываются на стороне сервера с использованием boost::asio::async_read_until
с соответствующим разделителем
Задача
- В течение двух дней система работала как положено
- На третий день на 18:55
сервер прочитал одно последнее сообщение от клиента, а затем перестал их читать. В журналах нет информации о новых данных.
- С 18:55
до 09:00
(14 часов) клиент не сообщил об ошибках. Таким образом, он отправил данные (около 700 Мб) успешно и ошибок не возникло.
- В 08:30
я начал расследование проблемы. Серверный процесс был жив, оба соединения между сервером и клиентом были живы.
- В 09:00
я подключился к процессу сервера с gdb
. Сервер находился в спящем состоянии, ожидая сигнала от системы. Мне кажется, я случайно нажал Ctrl + C и, возможно, там было какое-то сообщение.
- Позже в логах я нашел сообщение с чем-то вроде «системный вызов прерван». После этого оба соединения с клиентом были разорваны. Клиент переподключен и сервер начал нормально работать.
- Первое сообщение, обработанное сервером, было помечено как 18:57
на стороне клиента. Поэтому после возобновления нормальной работы сервер не отбрасывал все сообщения до 09:00
, они где-то хранились и после этого обрабатывали их соответствующим образом.
Вещи, которые я пробовал
- Имитация сценария выше. Поскольку сервер сбрасывал все входящие сообщения, я написал небольшой скрипт, который представлялся как клиент и снова отправил все сообщения обратно на сервер. Сервер был сброшен с ошибкой out of memory
, но, к сожалению, это произошло из-за высокой загрузки данных (на этот раз около 3 Гб / час), а не из-за той же ошибки. Поскольку был вечер пятницы, у меня не было времени, чтобы правильно повторить эксперимент.
- Тем не менее, я запускаю сервер через Valgrind, чтобы обнаружить возможные утечки памяти. Ничего серьезного не было найдено (за исключением того факта, что сервер был сброшен из-за высокой нагрузки), никаких значительных утечек памяти.
Вопросы
- Где были эти 700 Мб данных, которые отправил клиент, а сервер не получил? Почему они были постоянными и не потерялись, когда сервер перезапустил соединение?
- Мне кажется, что проблема связана с тем, что сервер не получает сообщение от boost::asio::io_service
. Буфер заполняется данными, но не обращаются к обработчику чтения. Может ли это быть проблемой на стороне ОС? Что-то не так с асинхронными вызовами? Если это так, как это можно проверить?
- Что я могу сделать, чтобы определить источник проблемы? Как я уже сказал, у меня закончились вменяемые идеи, и каждый эксперимент стоит очень дорого с точки зрения времени (для перевода системы в описанное состояние требуется около двух-трех дней), поэтому мне нужно выполнить как можно больше проверок для эксперимента, Я мог бы.
Буду признателен за любые идеи, которые я могу использовать, чтобы добраться до ошибки.
Обновление: Хорошо, похоже, что ошибка была в синхронном write
Оставлено в середине асинхронного взаимодействия клиент-сервер.Поскольку оба соединения жили в одном потоке, этот синхронный write
по какой-то причине блокировал поток, и все взаимодействие как по команде, так и по соединению данных прекратилось.Итак, я изменил его на асинхронную версию, и теперь он, кажется, работает.