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

StackOverflow https://stackoverflow.com/questions/410039

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение 2

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

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

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

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

Другие советы

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

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

  2. Видите ли вы какие-либо потенциальные проблемы с моим методом?

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

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

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

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

Филлюминати

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

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

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

  • MQ 460000 tps
  • пара разъемов 400000 tps

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

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

Спасибо

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

/блеи/

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top