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

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

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

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

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

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

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

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

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

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

`TIME_WAIT`-подобный статус, так как это время ожидания используется в случае, если паразитные пакеты от соединения все еще блуждают по Интернету. Концерн не применяется на местном уровне.

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

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

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



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



 возможно, это зависит от создаваемого приложения?

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

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

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

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

Глядя на`man msgrcv` Я не вижу аналога сокетов`MSG_PEEK`, Редко нужно, но иногда оказывается весьма кстати.

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

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

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

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

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

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