Подтвердить что ты не робот

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

Лучше ли использовать очереди сообщений 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.

Спасибо заранее.

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

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