Использование очередей сообщений POSIX вместо TCP-сокетов - как установить "соединение"?

У меня есть клиентские и серверные программы, которые теперь обмениваются данными через TCP. Вместо этого я пытаюсь использовать очереди сообщений POSIX (в случае, если клиент и сервер находятся на одной машине, конечно). Я надеюсь, что это улучшит производительность (в частности, за счет уменьшения латентности).

Я разработал большую часть этого, но не уверен в одном: как установить "соединение". Сервер принимает соединения от нескольких клиентов одновременно, поэтому у меня возникает соблазн эмулировать процесс установления соединения TCP следующим образом:

  • Сервер открывает очередь с известным именем и непрерывно читает ее (он может использовать select(2) как с TCP).
  • Клиент открывает три очереди: два с произвольными именами (включая некоторую уникальность, такую ​​как PID, чтобы избежать коллизий), и один с известным именем, используемым сервером.
  • Клиент отправляет сообщение "подключиться" к очереди сервера, включая имена очереди клиентов (один предназначен для трафика между клиентами, а другой для обратного).
  • Сервер открывает очереди, указанные в сообщении о подключении клиента, и начинает читать (выбирать) с клиентского сервера.
  • Клиент закрывает очередь сервера с известным именем. Двухсторонняя связь продолжается с использованием двух очередей, названных клиентом (по одному для каждого направления).

Вероятно, вы можете увидеть, как эта схема похожа на общий метод TCP, и это не случайно. Однако я хотел бы знать:

  • Можете ли вы придумать лучший способ сделать это?
  • Вы видите какие-либо потенциальные проблемы с моим методом?
  • Есть ли у вас какие-либо другие мысли, в том числе о вероятности того, что использование очередей сообщений вместо TCP на одном компьютере фактически улучшит производительность (латентность)?

Имейте в виду, что я раньше не использовал очереди сообщений POSIX (я использовал IBM WebSphere MQ некоторое время назад, но это было совсем другое). Платформа - это Linux.

Ответы

Ответ 1

Я закончил реализацию этого в основном, как я описал, с несколькими улучшениями:

  • На шаге 2 я использовал GUID для имен очередей вместо включения клиентского PID.
  • На шаге 4 я добавил отправку сообщения "accept" от сервера к клиенту.
  • Когда какая-либо сторона желает завершить связь, она отправляет сообщение об отключении.

Квитирование выполняется проще, чем TCP, но кажется достаточным.

Что касается латентности: это намного лучше. Примерно на 75% меньше времени ожидания, используя очереди сообщений POSIX вместо TCP на одном компьютере. Мои сообщения имеют порядок по 100 байт.

Ответ 2

  • Можете ли вы придумать лучший способ сделать это?

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

  • Вы видите потенциальные проблемы с моим методом?

    Очереди сообщений системы V и фило именованные каналы оба абсолютно прекрасны. Трубы Fifo похожи на обычные трубы, поэтому вы можете читать() и писать() с минимальными изменениями кода. Очереди сообщений системы V требуют помещения данных в структуру и вызова msgsnd(). Однако любой из этих подходов был бы прекрасен.

  • Есть ли у вас какие-либо другие мысли, в том числе о вероятности того, что использование очередей сообщений вместо TCP на одном компьютере фактически улучшит производительность (латентность)?

    Мои другие мысли таковы, что, как вы сказали, вам нужно разработать технику, чтобы каждый клиент имел уникальный идентификатор. Один из подходов состоит в том, чтобы добавить pid в структуру, через которую вы проходите, или для согласования уникального идентификатора с родителем/мастером в начале. Другое замечание заключается в том, что преимущество очередей сообщений System V заключается в том, что вы слушаете "выборочные" сообщения, чтобы вы могли идеально использовать одну очередь с сервера для всех клиентов, при этом каждый клиент ожидал другого сообщения.

    Я понятия не имею, какой метод дает вам оптимальную пропускную способность в вашем программном обеспечении. Возможно, не стоит использовать очереди сообщений System V, но вы можете принять это решение.

Philluminati

Ответ 3

Я сравнивал производительность posix MQ и пару сокетов TCP/IP.

Демо-программа имеет два потока, один для записи, а другой для чтения.

В результате получается, что posix MQ быстрее,

  • MQ 460000 tps
  • socketpair 400000 tps

Ответ 4

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

Вы сравнили решение на основе POSIX-MQ с локальными сокетами UNIX или сокетами TCP?

Спасибо

Ответ 5

Как вы это сделали, когда select() не работает в очередях сообщений? Что это Sys V или POSIX? Зачем прикладывать дополнительные усилия для создания GUID в PID-таблице поиска, когда PID гарантированно будет уникальным и меньше хранилище (целое число)?

/блее/

Ответ 6

Вы также можете использовать очереди сообщений для IPC в программах, которые находятся на разных компьютерах, в таких случаях вы можете использовать ZeroMQ (http://www.zeromq.org) или других API-интерфейсов очереди сообщений, я также предлагаю вам рассмотреть их и протестировать их тоже.