El Martes, 26 de Agosto de 2008 04:29, Alejandro Vargas escribió:
> 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.

Correcto. Para también que la noción de "tener algo para mandar" 
y "haber mandado algo" no está bien definida. Implica un estado para 
cada bloque de datos (mandado/no mandado) que actualmente no está 
almacenado en el equipo, sino en el servidor que accede a los 
equipos, les lee los datos y los guarda en una base de datos.
Pero es una buena idea. El servidor, cuando reciba la conexión y lea 
los datos, podría marcar en el equipo como ya leídos los bloques de 
datos que ya no le interesen. El equipo si no hay ningún bloque de 
datos marcado se abstiene de intentar conectarse. A los 5 min se va a 
generar un bloque nuevo de datos, inicialmente no marcado y le van a 
venir las ganas de conectarse de nuevo. Más un retardo aleatorio 
(porque los 10000 equipos están sincronizados y obtienen los datos al 
mismo tiempo), más un límite en la cantidad de conexiones que se le 
dé la gana de aceptar al servidor, y estaríamos. Como desventaja, 
habría más tráfico por los comandos del servidor al equipo marcando 
bloques como no interesantes y por los intentos de conexión 
rechazados por el servidor.

 
> 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.

Dicha rutina es un autómata de estados finitos. Podría modificar 
algunas de las reglas de transición de estado para que no efectivice 
la conexión a menos que haya bloques no marcados como no 
interesantes. La desconexión ya estaría bien manejada (el servidor 
corta la conexión cuando le venga bien).

Me perdería la capacidad de tener al equipo en línea para mandarle un 
comando, ver su configuración o estado en un momento arbitrario, 
accederlo desde otro host, etc. pero lo fundamental andaría.



> Del otro lado el servidor debería tener la capacidad de descartar
> bloques duplicados y demás.

No creo que modifique el protocolo. Aún cuando el equipo sea el que se 
conecte al servidor, una vez conectado el servidor iniciará la 
transacción y pedirá los datos que tenga ganas.


> > 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.

Imaginatelo como un arreglo de 96 posiciones de unas estructuras de 
datos de unos 768 bytes. Podría buscar un bit no usado por algún 
lugar de esas estructuras y decidir que signifique "bloque no 
interesante". O armar un arreglo aparte de 12 bytes donde cada bit 
signifique que el respectivo bloque no es interesante. Al rellenar un 
nuevo elemento de datos, el bit correspondinete nace 
como "interesante". Verificar luego que todos los bytes de un arreglo 
de 12 bytes sean 0 es trivial. (Un OR de los 12 bytes y listo).

Luego tendría que implementar un comando para que esos bits sean 
manipulables por el servidor.


> 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.

Correcto.


> > 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.

No es complicado de hacer lo que decís, pero se pierde bastante 
funcionalidad.


> > 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.

A 0,01 pesos el kB excedente de tráfico... 5 paquetes (SYN, SYN+ACK, 
ACK, FIN, FIN+ACK) cada 5 min, son 480 al día, o 14400 al mes. El 
tamaño mínimo de los paquetes IP creo que era 320 bytes, o sea que 
terminan siendo 4500 kB extra al mes, o 45 pesos extra al mes, 
comparado con los 12 pesos por 5 MB al mes que es una excelentísima 
tarifa conseguible... sería la muuerte!


> 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.

Sí, yo no necesitaría ir largando hijos y teniéndolos listos. Que se 
caguen y esperen el tiempo que lleve el fork().


> De esa forma, con un número relativamente chico de procesos
> servidores se puede atender a muchísimos clientes.

pero no simultáneamente. Pero cumple, a costa de sacrificar algunas 
flexibilidades y comodidades. Lo voy a seguir masticando.



> > 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.

El protocolo contempla unos "mensajes no solicitados" que se adaptan 
mejor a lo que planteás, pero nunca implementé esa parte del 
protocolo.


> A ver... por lo que dijiste deduzco que de perderse la
> comunicación, reintentaban en un lapso de entre  10 y 120,
> segundos, ¿no?

Reintentan de inmediato (bueno, 2 segundos después). Pero que la 
conexión esté establecida de nuevo le lleva a la red entre 10 y 120 
segundos.


> ¿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.

Es más simple, pero me gusta más lo que expliqué antes, con las ganas 
de conectarse del equipo desacopladas de los tiempos del algoritmo de 
reconexión.


> > 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).

Como yo me lo imagino, cuando haya datos nuevos o no marcados como ya 
vistos por el servidor, el equipo va a querse conectar con el máximo 
de empeño. Le agrego una espera aleatoria entre intentos de unos 
pocos segundos, y listo. Cuando logre conectarse y el servidor logre 
chuparle todos los datos y marcárselos como ya vistos, que lo 
desconecte (o le mande el comando de desconexión ya existente al 
equipo) y listo: el equipo permanecerá desconectado hasta que de 
nuevo haya datos nuevos (5 min).

-- 
Herr Groucho

ID Jabber: [EMAIL PROTECTED]
Señal distintiva: LU5MJR - 144,550 MHz FM.
Clave pública GPG: hkp://pks.lugmen.org.ar
Fingerprint GPG: B7BD 0FC7 D9A2 66F3 4EFC  45EE 7DE2 3932 597B 6354

Responder a