c++ - memoria - cola de mensajes en c
¿Qué es mejor para IPC local, colas de mensajes POSIX(mqueues) o sockets de dominio Unix(local)? (3)
¿Es mejor utilizar las colas de mensajes POSIX o los sockets de dominio Unix para la comunicación IPC local?
He trabajado con sockets de Unix entre máquinas (no de dominio) y recuerdo que hacer y romper la conexión causaría que los sockets se prolonguen un poco antes de que finalmente se desactiven. Además, si deseaba un intercambio "confiable", tenía que usar TCP o diseñar la aplicación para devolver un ACK. No estoy seguro si esto también se aplica a los sockets de dominio Unix sin embargo.
En mi proyecto actual necesitamos IPC local. Mi primera reacción fue usar POSIX MQueues, ya que los he usado antes para la mensajería local. Sin embargo, un compañero de trabajo está sugiriendo sockets de dominio Unix en su lugar.
¿Es uno mejor que el otro, o es una cuestión de familiaridad con la programación? ¿O tal vez depende de la aplicación que se está creando?
En un panorama general, la aplicación en la que estamos trabajando sigue un modelo de cliente / servidor. Los clientes envían mensajes al servidor para "hacer algo". Sin embargo, el cliente no espera una respuesta "está lista", aunque sí quieren saber si su solicitud ha sido recibida o no.
La lógica básica para el lado de envío es:
connect to server
send request
note if the send worked or not
disconnect from server
Puede haber cientos de clientes en un servidor.
Estamos ejecutando en un sistema SMP (4-8 núcleos) que ejecuta el sistema operativo Linux.
Gracias por adelantado.
¿Es uno mejor que el otro, o es una cuestión de familiaridad con la programación? ¿O tal vez depende de la aplicación que se está creando?
Las colas de mensajes de SysV comparadas con los sockets de datagramas de dominio de UNIX tienen las principales diferencias que conozco:
Puede
poll()
socket, pero no puede enviar cola.La cola de mensajes es global y podría (y generalmente requiere) una participación administrativa: limpiar los recursos antiguos de SysV que cuelgan es una de las muchas rutinas diarias de sysadmin. Mientras que la semántica del dominio UNIX es mucho más simple y las aplicaciones generalmente pueden mantenerlo completamente internamente sin la participación del administrador del sistema.
(?) La cola de mensajes es persistente, puede retener mensajes de las sesiones anteriores. (No puedo recordar ese bit con precisión, pero el IIRC me sucedió más de una vez).
Mirando el
man msgrcv
no veo el análogo deMSG_PEEK
de socket. Rara vez se necesita, pero a veces resulta bastante práctico.La mayoría de las veces, los usuarios prefieren utilizar en la configuración los nombres simbólicos, no la identificación de la clave numérica. Falta de claves simbólicas La OMI es una supervisión bastante grave de parte de los diseñadores de interfaces de SysV.
Al igual que con todos los recursos de SysV, su administración es el PITA principal. Si deja que el sistema decida el ID de la cola de mensajes, debe ocuparse de compartirlo adecuadamente con otras aplicaciones. (Y también tiene que decirle a los administradores de alguna manera que la identificación debe eliminarse eventualmente). Si permite configurar la clave para la cola de mensajes, es posible que tenga problemas triviales porque la aplicación ya está utilizando la identificación o es un remanente de la ejecución anterior. (Ver que los servidores se reinician solo porque se quedan sin recursos de SysV es bastante común).
En general, evito los recursos de SysV cuando es posible: la falta de soporte de poll()
en las circunstancias más comunes es un factor decisivo.
Sin embargo, el cliente no espera una respuesta "está lista", aunque sí quieren saber si su solicitud ha sido recibida o no.
Ese es un dilema común del procesamiento transaccional. La respuesta general es (como en los RDBMS) que no puede y después de la interrupción de la comunicación (bloqueo o lo que sea), la aplicación debe verificar si la solicitud ya se procesó o no.
De eso puedo decir que probablemente TCP sería una mejor opción. El cliente envía la solicitud y la declara como finalizada solo cuando recibe una respuesta positiva del servidor. El servidor, a menos que sea capaz de enviar la respuesta al cliente, debe revertir la transacción.
Los sockets de dominio UNIX no tienen que "demorarse" en un estado similar a TIME_WAIT
, ya que ese tiempo de espera se usa en caso de que haya paquetes extraviados de la conexión que todavía deambulan por Internet. La preocupación no se aplica localmente.
Los sockets de dominio UNIX pueden ser SOCK_STREAM
(como TCP) o SOCK_DGRAM
(como UDP), con la garantía añadida de que los sockets de datagramas de dominio de UNIX son confiables y no reordenan los datagramas.
Aún necesitará algún tipo de ACK (incluso con TCP) si quiere estar seguro de que su otra aplicación ha leído el mensaje que envió; después de todo, incluso si el send()
tuvo éxito, puede haberse estrellado antes de que tuviera la oportunidad de procesar el mensaje. (Esto también se aplica a las colas de mensajes; para estar totalmente seguro de que no se perderá un mensaje, la aplicación que recibe debe escribir la solicitud en un diario, vaciarla en el disco y luego enviar un acuse de recibo).
Estoy de acuerdo en que la elección es esencialmente una cuestión de familiaridad con la programación.
Yo sugeriría buscar en DBus para una aplicación de este tipo, aunque solo fuera por su interfaz de clasificación de datos y RPC (sincrónica y asíncrona). Utiliza los sockets de dominio de forma nativa y funciona muy bien después de una curva de aprendizaje inicial.