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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Philluminati

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

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

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

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

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

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

    Результатом является то, что posix MQ быстрее,

    • MQ 460000 tps
    • socketpair 400000 tps

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

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

    Спасибо

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

    / Блее /

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