Uso de colas de mensajes POSIX en lugar de sockets TCP: ¿cómo establecer una “conexión”?

6 minutos de lectura

Tengo programas de cliente y servidor que ahora se comunican a través de TCP. Estoy probando usar colas de mensajes POSIX en su lugar (en los casos en que el cliente y el servidor están en la misma máquina, por supuesto). Mi esperanza es que mejore el rendimiento (específicamente a través de una latencia reducida).

He resuelto la mayor parte, pero no estoy seguro de una cosa: cómo establecer la “conexión”. El servidor acepta conexiones de varios clientes al mismo tiempo, por lo que estoy tentado a emular el proceso de establecimiento de la conexión TCP de la siguiente manera:

  1. El servidor abre una cola con un nombre conocido y la lee continuamente (puede usar select(2) como con TCP).
  2. El cliente abre tres colas: dos con nombres arbitrarios (incluida alguna singularidad como PID para evitar colisiones) y una con el nombre conocido que usa el servidor.
  3. El cliente publica un mensaje de “conexión” en la cola del servidor, incluidos los nombres de cola del cliente (uno está designado para el tráfico de cliente a servidor y el otro para el tráfico inverso).
  4. El servidor abre las colas nombradas en el mensaje de conexión del cliente y comienza a leer (seleccionar) desde el cliente al servidor.
  5. El cliente cierra la cola del servidor con el nombre conocido. La comunicación bidireccional procede utilizando las dos colas nombradas por el cliente (una para cada dirección).

Probablemente pueda ver cómo este esquema es similar al método TCP común, y eso no es casualidad. Sin embargo, me gustaría saber:

  1. ¿Se te ocurre una forma mejor de hacerlo?
  2. ¿Ve algún problema potencial con mi método?
  3. ¿Tiene alguna otra idea, incluida la probabilidad de que el uso de colas de mensajes en lugar de TCP en la misma máquina mejore el rendimiento (latencia)?

Tenga en cuenta que no he usado colas de mensajes POSIX antes (utilicé IBM WebSphere MQ hace un tiempo, pero eso es bastante diferente). La plataforma es Linux.

Avatar de usuario de Philluminati
Philluminati

  1. ¿Se te ocurre una forma mejor de hacerlo?

    Tal vez eche un vistazo a los fifos (también conocidos como tuberías con nombre). Son como sockets de red pero para la máquina local. Son unidireccionales, por lo que es posible que deba crear dos, uno para cada dirección. Su pregunta no tiene ningún motivo de por qué usted está haciendo este cambio específicamente. No hay nada de malo en usar sockets para la comunicación de proceso a proceso. Son bidireccionales, eficientes, ampliamente compatibles y le dan la libertad de separar los procesos entre máquinas más adelante.

  2. ¿Ve algún problema potencial con mi método?

    Las colas de mensajes de System V y las canalizaciones con nombre FIFO están absolutamente bien. Las tuberías Fifo son como tuberías normales, por lo que puede leer () y escribir () con cambios mínimos de código. Las colas de mensajes de System V requieren colocar los datos en una estructura e invocar msgsnd(). Sin embargo, cualquier enfoque estaría bien.

  3. ¿Tiene alguna otra idea, incluida la probabilidad de que el uso de colas de mensajes en lugar de TCP en la misma máquina mejore el rendimiento (latencia)?

    Mis otros pensamientos son que, como dijiste, necesitas desarrollar una técnica para que cada cliente tenga un identificador único. Un enfoque sería agregar el pid a la estructura que pasa o negociar una identificación única con el padre/maestro al principio. La otra cosa a tener en cuenta es que el beneficio de las colas de mensajes de System V es que escucha mensajes “selectivos”, por lo que idealmente podría usar una cola del servidor a todos los clientes, con cada cliente esperando un mensaje diferente.

    No tengo idea de qué técnica le brinda el rendimiento más óptimo en su software. Realmente podría no valer la pena usar las colas de mensajes de System V, pero solo usted puede tomar esa decisión.

Philluminati

  • Usted dice que mi “pregunta no tiene ninguna razón de por qué está haciendo este cambio”. Lo mencioné: rendimiento (latencia). ¿Las colas de mensajes de System V son diferentes en funcionalidad a las de POSIX? Los POSIX que estoy usando (por ejemplo, mq_open (3)) no parecen admitir los mensajes “selectivos” que menciona.

    – John Zwink

    4 de enero de 2009 a las 3:59

  • Ahora he intentado usar canalizaciones con nombre. Son más lentos (al menos para pasar muchos mensajes pequeños) que las colas de mensajes POSIX.

    – John Zwink

    5 de enero de 2009 a las 16:41

Terminé implementándolo básicamente como lo describí, con algunas mejoras:

  • En el paso 2, utilicé GUID para los nombres de las colas en lugar de incorporar el PID del cliente.
  • En el paso 4, agregué el envío de un mensaje de “aceptación” del servidor al cliente.
  • Cuando cualquiera de las partes desea finalizar la comunicación, envía un mensaje de “desconexión”.

El protocolo de enlace es más simple que TCP, pero parece suficiente.

En cuanto a la latencia: es mucho mejor. Aproximadamente un 75 % menos de latencia usando colas de mensajes POSIX en lugar de TCP en la misma máquina. Mis mensajes son del orden de 100 bytes cada uno.

avatar de usuario de lxyfirst
lxyprimero

Comparé el rendimiento de posix MQ y un par de sockets TCP/IP.

El programa de demostración tiene dos subprocesos, uno para escribir y otro para leer.

El resultado es que posix MQ es más rápido,

  • MQ 460000 tps
  • par de enchufes 400000 tps

Me encontré con un problema similar, desarrollo una aplicación en tiempo real y necesito una técnica IPC con una funcionalidad similar a la de los sockets y una latencia mínima.

¿Ha comparado su solución basada en POSIX-MQ con sockets locales UNIX o solo sockets TCP?

Gracias

¿Cómo hiciste esto cuando select() no funciona en las colas de mensajes? ¿Qué es Sys V o POSIX? ¿Por qué hacer el esfuerzo adicional de crear una tabla de búsqueda de GUID a PID cuando se garantiza que el PID es único y es un almacenamiento más pequeño (entero)?

/blee/

  • Esto realmente debería ser un comentario sobre mi respuesta. De todos modos: Select funciona con colas de mensajes POSIX, que son las que estoy usando. No hay una tabla de búsqueda de GUID a PID: el GUID se comunica entre los procesos y el PID nunca se usa. Los PID no son únicos: se reciclan en la mayoría de los sistemas.

    – John Zwink

    17 de febrero de 2009 a las 23:29

avatar de usuario de gst
gst

También puede usar Message Queues for IPC en programas que residen en diferentes máquinas, en tales casos puede usar ZeroMQ(http://www.zeromq.org) u otras API de cola de mensajes, también le sugiero que las considere y las pruebe también.

  • Esto realmente debería ser un comentario sobre mi respuesta. De todos modos: Select funciona con colas de mensajes POSIX, que son las que estoy usando. No hay una tabla de búsqueda de GUID a PID: el GUID se comunica entre los procesos y el PID nunca se usa. Los PID no son únicos: se reciclan en la mayoría de los sistemas.

    – John Zwink

    17 de febrero de 2009 a las 23:29

¿Ha sido útil esta solución?