Что лучше для локальных IPC, очередей сообщений POSIX (mqueues) или доменных (локальных) сокетов Unix? - PullRequest
21 голосов
/ 23 сентября 2010

Лучше ли использовать очереди сообщений POSIX или доменные сокеты Unix для локальной связи IPC?

Я работал с сокетами Unix между машинами (не доменами), и я помню, что создание и разрыв соединения приводил к тому, что сокеты задерживались некоторое время, прежде чем они наконец исчезли. Более того, если вы хотели «надежного» обмена, вам нужно было использовать TCP или разработать приложение для возврата ACK. Я не уверен, если это также относится к сокетам домена Unix.

В моем текущем проекте нам нужен локальный IPC. Моей первой реакцией было использование POSIX MQueues, так как я использовал их раньше для локальных сообщений. Однако сотрудник предлагает вместо этого использовать доменные сокеты Unix.

Одно лучше другого или дело в программировании? Или, может быть, это зависит от создаваемого приложения?

В целом, приложение, над которым мы работаем, следует модели клиент / сервер. Клиенты отправляют сообщения на сервер, чтобы «сделать что-то». Однако клиент не ждет ответа «все готово», хотя он и хочет знать, был ли получен запрос или нет.

Основная логика для отправляющей стороны:

connect to server
send request
note if the send worked or not
disconnect from server

На одном сервере могут находиться сотни клиентов.

Мы работаем в системе SMP (4-8 ядер) под управлением ОС Linux.

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 23 сентября 2010

Доменные сокеты UNIX не должны «задерживаться» в TIME_WAIT -подобном состоянии, поскольку это время ожидания используется в случае, если паразитные пакеты от соединения все еще блуждают по Интернету.Эта проблема не распространяется локально.

Сокеты домена UNIX могут быть либо SOCK_STREAM (например, TCP), либо SOCK_DGRAM (например, UDP), с дополнительной гарантией того, что сокеты дейтаграммы домена UNIX надежны и не• переупорядочивать дейтаграммы.

Вам все еще понадобится какой-нибудь ACK (вы делаете это даже с TCP), если вы хотите быть уверенным , что ваше другое приложение прочитало отправленное вами сообщение;в конце концов, даже если send() преуспел, он мог произойти сбой до того, как у него была возможность обработать сообщение.(Это относится и к очередям сообщений - чтобы быть полностью уверенным, что сообщение не будет потеряно, приложение-получатель должно записать запрос в журнал, сбросить его на диск и затем отправить подтверждение).

Я согласен, что выбор, по сути, зависит от программирования.

4 голосов
/ 23 сентября 2010

Одно лучше другого или дело в программировании?Или, может быть, это зависит от создаваемого приложения?

Очереди сообщений SysV по сравнению с сокетами дейтаграмм домена UNIX имеют основные отличия, о которых я знаю:

  • Вы можете poll() сокет, но не можете очередь сообщений.

  • Очередь сообщений является глобальной и может (и обычно делает) требовать некоторого административного вмешательства: очистка старых зависших ресурсов SysV - это одноиз многих ежедневных процедур сисадмина.Хотя семантика домена UNIX намного проще, и приложения, как правило, могут поддерживать его полностью внутренне без участия системного администратора.

  • (?) Очередь сообщений является постоянной, она может сохранять сообщения из старых сеансов.(Не могу вспомнить этот бит точно, но IIRC, что происходило со мной не раз).

  • Глядя на man msgrcv Я не вижу аналог сокета MSG_PEEK.Редко требуется, но иногда бывает очень удобно.

  • В большинстве случаев пользователи предпочитают использовать в конфигурации символические имена, а не числовой идентификатор ключа.Отсутствие символических ключей IMO является довольно серьезным упущением со стороны разработчиков интерфейсов SysV.

Как и для всех ресурсов SysV, их управление является основным PITA.Если вы разрешите системе определять идентификатор очереди сообщений, вам придется позаботиться о том, чтобы правильно делиться им с другими приложениями.(И вы также должны как-то сказать администраторам, что идентификатор должен быть удален в конце концов).Если вы разрешите настроить ключ для очереди сообщений, то у вас могут возникнуть тривиальные проблемы: идентификатор уже используется каким-либо приложением или является остатком предыдущего запуска.(Видеть, что серверы перезагружаются только потому, что у них заканчиваются ресурсы SysV, довольно распространено.)

В общем, я избегаю ресурсы SysV, когда это возможно: отсутствие поддержки poll() в большинстве обычных обстоятельств нарушает условия сделки.

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

Это общая дилемма транзакционной обработки.Общий ответ (как в RDBMS) вы не можете, и после прерывания связи (сбой или что-то еще) приложение должно проверить себя, был ли запрос уже обработан или нет.

Из этого я могу сказать, что, вероятно, TCPбудет лучшим выбором.Клиент отправляет запрос и объявляет его завершенным, только когда получает положительный ответ от сервера.Сервер, если он не может отправить ответ клиенту, должен откатить транзакцию.

3 голосов
/ 23 сентября 2010

Я бы посоветовал взглянуть на DBus для такого приложения, хотя бы для их сортировки данных и RPC-подобного интерфейса (как синхронного, так и асинхронного).Он изначально использует доменные сокеты и действительно хорошо работает после начальной кривой обучения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...