Una sola conexión Modbus: cuando vigilar rompe lo vigilado
El lazo de control llevaba meses funcionando. Añadimos un segundo proceso, sin ninguna capacidad de escritura, cuyo único trabajo era leer telemetría del mismo controlador y guardarla para las gráficas. A partir de ese momento, ninguno de los dos funcionaba de forma fiable.
El log del lazo de control se llenó de No response received y de
avisos de transaction id que no coincidía con el de la petición. El de
telemetría, de lo mismo. Los dos procesos estaban bien escritos y los dos estaban
rotos.
El dato que no viene en la hoja de características
Muchos controladores industriales con Modbus TCP —y prácticamente todas las pasarelas Modbus TCP a RS-485 baratas— aceptan una sola conexión TCP simultánea. No es un fallo: es una implementación mínima y perfectamente legítima del estándar, hecha en un microcontrolador con memoria contada. Lo que casi nunca ocurre es que esté escrito en la documentación.
El comportamiento cuando llega la segunda conexión varía y ninguna variante es agradable:
- El equipo rechaza la nueva conexión. Es el mejor caso: el proceso que llega tarde falla ruidosamente y sabes lo que pasa en un minuto.
- El equipo echa la conexión anterior y acepta la nueva. Los dos clientes se turnan para desconectarse mutuamente, reconectan, y el sistema entra en un carrusel donde cada uno funciona a ratos.
- El equipo acepta las dos y mezcla las respuestas. Cada cliente recibe contestaciones a preguntas que no ha hecho, con un identificador de transacción que no reconoce, las descarta y acaba en timeout.
El tercer caso es el que produce el síntoma más confuso: en el cable hay tráfico
constante, el equipo responde, el ping va perfecto y el analizador de
protocolo muestra respuestas bien formadas. Todo parece sano salvo que nadie
consigue leer un registro.
El diagnóstico son treinta segundos
Cuando dos procesos hablan con un mismo equipo y ambos fallan de forma intermitente, la comprobación es inmediata: para uno.
systemctl stop telemetria.service
journalctl -u control.service -f
Si el otro se cura al instante y de forma limpia, ya está: no hay que buscar en la red, ni en los tiempos de espera, ni en la calidad del cable. Es concurrencia. La prueba es concluyente en un sentido y no cuesta nada.
Merece la pena insistir en lo contraintuitivo del asunto, porque es lo que hace que se tarde días en dar con ello: el proceso que rompió el sistema no escribe nada. Es un lector pasivo, la pieza que uno descarta primero cuando busca al culpable de que un actuador se comporte mal.
Vigilar puede romper lo vigilado
Ese es el fondo del asunto, y va bastante más allá de Modbus. Al añadir telemetría a un sistema de control introdujimos una dependencia nueva entre una pieza crítica —el lazo que garantiza que la planta no exporta— y una pieza que no lo es en absoluto: unas gráficas bonitas.
Y la dependencia iba en el sentido equivocado. Un fallo, un despliegue o simplemente el arranque del proceso de gráficas podía dejar ciego al lazo de control. La jerarquía de criticidad estaba escrita en nuestra cabeza, pero no en la arquitectura.
Regla. Un recurso industrial que no admite concurrencia tiene un único dueño, y el dueño es siempre el proceso más crítico. Los demás piden los datos al dueño; no van a la fuente por su cuenta.
Las tres arquitecturas posibles
Resolver esto tiene tres formas, en orden de preferencia:
1. Dueño único con reparto. El lazo de control mantiene la única conexión y publica lo que lee —en memoria compartida, en una cola, en un endpoint local o directamente en la base de datos de series temporales—. La telemetría consume de ahí. Ventajas: una sola conexión por definición, el problema no puede volver, y los datos que se grafican son exactamente los que ve el control, lo cual vale oro cuando hay que reconstruir un incidente. Coste: acoplas dos funciones en un proceso, y ese proceso ya no puede reiniciarse alegremente.
2. Conexión no persistente con turno. Ninguno de los dos mantiene el socket abierto: cada uno abre, pregunta, cierra, y un cerrojo compartido garantiza que no se solapan. Es menos invasivo y a veces es lo único posible si los procesos son de terceros. Coste: el ciclo de abrir y cerrar TCP se paga en cada lectura, y en un lazo con watchdog ajustado ese tiempo hay que medirlo, no suponerlo.
3. Un multiplexor delante. Un proxy Modbus que sí acepta varias conexiones y las serializa contra el equipo. Resuelve el caso general y es la respuesta correcta cuando hay muchos consumidores, pero mete un componente más en el camino crítico: si el proxy se cae, se cae el control.
En una planta con un lazo de seguridad, la primera opción gana casi siempre. La telemetría puede perderse un rato; el anti-vertido no.
Cómo evitar el siguiente
La lección operativa es más útil que la técnica. Cuando se añade un segundo consumidor a cualquier equipo de campo, la pregunta «¿cuántas conexiones simultáneas aguanta esto?» pasa a formar parte de la lista de comprobación antes de habilitar el servicio, y se responde probándolo, no leyendo la documentación —donde, insistimos, no suele estar—.
Y conviene revisar el inventario con esa pregunta en la mano: si un equipo ya
tiene un consumidor persistente, cualquier proceso nuevo que lo apunte es un
incidente esperando a que alguien haga systemctl enable.
El poso
- Un equipo Modbus TCP puede admitir una sola conexión, y eso rara vez está documentado. Asúmelo hasta demostrar lo contrario.
- Dos procesos fallando a la vez contra el mismo equipo: para uno. El diagnóstico cuesta treinta segundos.
- Un lector pasivo puede tumbar un lazo de control. «No escribe» no significa «no molesta».
- Los recursos que no admiten concurrencia necesitan un dueño explícito, y debe serlo la función más crítica.
¿Te suena de tu planta? Esto sale de operar instalaciones reales todos los días. Si tienes un problema parecido, cuéntanoslo: la primera conversación es con un ingeniero, no con un comercial.
Hablar con un ingeniero Probar el simulador →
VOLTIA