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