El día 25 de agosto de 2008 22:13, Herr Groucho <[EMAIL PROTECTED]> escribió:
> Cada equipo genera 768 byes de datos cada 5 min, de los cuales interesará
> leer la mitad salvo ocasiones especiales. Cada equipo tiene buffers no
> volátiles para almacenar hasta 96 bloques de datos, que a razón de 1
> bloque cada 5 min, permite tener pendientes de leer los datos generados
> durante 8 horas.
> Para que los equipos no estén todo el tiempo conectados, tendría que
> hacerlos trabajar como servidores, no como clientes,
No necesariamente. Simplemente cada 5 minutos cuando tengan un nuevo
bloque de datos disponible para enviar, inician una conexión y si esta
se estableció correctamente lo envían y la cierran. Supongo que de
todas formas el proceso será más o menos así (conectarse si la
conexión está cerrada) sólo que (estoy adivinando) ahora se conectan
aunque no tengan nada que mandar. Tal vez sea tan fácil como tocar la
rutina que establece la conexión para que si no hay nada en el buffer
no se conecte. La rutina de reconexión debería ejecutarse digamos cada
1 minuto, y si se conecta correctamente tendría que ejecutar la rutina
de envío para transmitir el buffer completo.
Del otro lado el servidor debería tener la capacidad de descartar
bloques duplicados y demás.
> Siendo clientes, para que no estén todo el tiempo conectados, tendría que
> idear e implementar un algoritmo para decidir cuándo deberían conectarse
> más sofisticado que el actual ("siempre").
Bueno, me parece que "si longitud de buffer >0" puede no ser tan
complicado de implementar, pero no conozco el equipo. Supongo que
actualmente ya tendrá una manera de reconectar si se ha cortado, así
que tan reducido no puede ser el código de todas formas.
> Podría hacer que se quieran
> conectar cada cierto tiempo y pernamezcan conectados mientras haya
> actividad,
Simplemente si hay datos conectarse y enviar lo que haya. Cuando no
haya datos desconectarse. A mi me suena sencillo pero como te dije, no
conozco nada de la implementación que tenés.
> o podría hacer que quisieran conectarse todo el tiempo y que
> sea el servidor el que maneje cuántos se conectan realmente no aceptando
> todas las conexiones,
Hummm... no me suena muy bien. Siendo tantos hay muchas probabilidades
de que alguno tenga "mala suerte" y no le toque en muchas horas...
> pero tampoco quiero derrochar tráfico con el
> establecimiento y terminación de las conexiones TCP al pedo.
Sí, eso también. Me parece mala idea.
>> Tal vez sea más sensato establecer la
>> conexión, mandar el dato y cerrarla.
>
> La ventaja de tenerlos conectados todo el tiempo (además de que es lo más
> fácil de implementar) es el ahorro en tráfico al no derrocharse bytes en
> establecer y terminar conexiones TCP.
Bueno, pero como mucho una conexión cada 5 minutos no debería generar
tanto tráfico. Sobre todo si buscás la manera de que no sean todos al
mismo tiempo.
En tu programa simplemente podés aceptar tantas conexiones simultáneas
como diga una configuración. Yo creo que tu caso se parece muchísimo
al de un servidor web: tenés miles o cientos de miles de usuarios
realizando conexiones cortas. En el caso de un servidor web es incluso
más complicado porque no sabés qué tan larga será la conexión y qué
tan pronto querrán conectarse de nuevo, por eso el http implementa la
capacidad del "connection: keep-alive", o sea no cerrar una vez
transmitidos los datos, pero de todas formas el servidor mantiene la
conexión por un ratito: si el cliente no pide datos termina por
cerrarla.
En esa situación fijate que un servidor web puede atender cientos de
miles de comunicaciones con pocos servidores (digamos unos 100).
Supongo que sabrás como funciona Apache pero para el que no sepa, al
arrancar larga una cantidad (configurable) de hijos por las dudas,
para que ya estén cargados y en memoria listos para atender llamadas,
digamos por ejemplo unos 30. Si no tienen trabajo los va cerrando,
pero mantiene una cantidad mínima (también configurable), digamos unos
20. A medida que van entrando más y más pedidos simultáneos, va
largando más hijos hasta un máximo (otra vez configurable), digamos
unos 100. Alcanzado ese límite, de por ejemplo 100 conexiones
simultáneas no es que fallen las conexiones o de algún error.
Simplemente al intentarse más conexiones el cliente tiene que esperar
un poquito a que se cierre alguna y le toque.
De esa forma, con un número relativamente chico de procesos servidores
se puede atender a muchísimos clientes. Y me parece que es justo el
caso tuyo pero esta vez incluso más fácil porque sabés que una vez que
hayan transmitido, no necesitarán conectarse al menos en 5 minutos así
que podés cerrar la conexión con toda tranquilidad.
> "pre-fork". Pero eso es sólo para aumentar el rendimiento ahorrándose el
> tiempo de ejecutar un fork. Acá no me parece que ese factor sea
> determinante del desempeño, toda vez que los enlaces de datos de cada
> equipo remoto son de 9,6 kbps
Sí, es más sencillo tu caso todavía. Simplemente, tal como lo tenías
planteado, para cada cliente que llame le largás un servidor. El único
cambio que tendrías que hacer es que cuando el cliente mande un código
de "TOF" ("That's All Folks)... bueno, EOT, (tradicionalmente el
código 4) si lo querés hacer más serio, le cortás... y él es tan
amable de no volverte a llamar si no tiene nada que decir...
> solos, encapsulados dentro de un paquete UDP, que no es el caso. El
> protocolo de aplicación es tal que a los equipos hay que mandarles una
> pregunta para que devuelvan los datos, y en la pregunta se puede elegir
> cuántos y cuáles datos.
Ahh!... bueno, y supongo que cambiar eso no es una opción... ok.
A ver... por lo que dijiste deduzco que de perderse la comunicación,
reintentaban en un lapso de entre 10 y 120, segundos, ¿no? ¿Podrías
subir ese tiempo a 5 minutos? Entonces tendrías cada 5 minutos un
cliente llamándote para preguntarte ¿Che, necesitás algo de mi? Vos le
descargarías lo nuevo que tuviera y cortarías. Si el trámite fallara
se reintentaría en los 5 minutos siguientes.
> El sistema nació con los 10000 equipos en el rol de servidores. El
> servidor se iba a conectar a ellos (a razón de unas pocas decenas cada
> vez) y sacarle los datos que hiciera falta. Pero eso requería direcciones
> IP fijas para que el servidor supiera a dónde ir a conectarse. Ese
> servicio no está siempre disponible y hay que flexibilizar el sistema y al
> hacerlo, me gustaría reescribir la menor cantidad de código de los equipos
> embebidos.
Si, entiendo el problema. Bueno, pienso que si hicieras que en lugar
de empecinarse en mantener la conexión abierta, en caso de cortarse
tardaran 5 minutos en reintentar, tendrías bastante solucionado el
problema. Si a demás querés hacerlo más inteligente, el dispositivo
podría decidir cada cuanto reintentar en función del motivo de la
última desconexión (intencional o por una falla) o en función de si
tiene datos sin transmitir (si es que tiene manera de saberlo).