Sockets - 100,000 peticiones diarias

Hola a todos los miembros de javamexico. Acudo nuevamente a ustedes para ver si alguno de los expertos me puede guiar un poco

Estoy planeando hacer una aplicación similar a la del metrubus, en donde pasen la tarjeta por un lector y mande la información del usuario a un server. Yo no voy a desarrollar nada de esta parte de hardware, lo que a mi me toca es hacer una aplicación en un servidor que esté recibiendo todas las peticiones que se hagan cuando los usuarios pasen sus tarjetas por los lectores.

La aplicación va a recibir tramas de datos de los lectores de tarjetas pero me espanta un poco porque van a ser mas o menos 100,000 peticiones diarias :S

Creo que tengo que utilizar sockets para este desarrollo cierto? Mi duda es si tengo que hacer un threadpool muy grande para tantisimas peticiones, no se si hay alguien por aquí que ya haya hecho algo similar con sockets para que me guíe cómo puedo hacer la programación para no tener tantos problemas de performance por el altisimo grado de peticiones diarias.

Me recomiendan utilizar postgresql para tantos registros? No se me harán lentas las tablas con tantisimos registros a la hora de buscar datos históricos ?

Agradezco infinitamente su tiempo y su ayuda, gracias

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de beto.bateria

Verifica como manda los datos

Verifica como manda los datos el hardware al pasar la tarjeta, podrias intentar que pasen las peticiones por http y usar un contenerdor como tomcat (hay algunos mas pequeños), asi ya no tendrias que programar el administrador de peticiones.

HTTP vs Sockets

Gracias por tu respuesta beto.bateria.
Si lo hago con http y un contenedor de servlets es problable que tenga mejor desempeño? Con sockets tengo entendido que puedo hacer un pool de threads pero cómo le hace un contenedor de servlets para manejar las peticiones que están en espera?

Gracias por su ayuda

Imagen de ezamudio

HTTP

Cuántos lectores de tarjetas son? Tienes que considerar el número de lectores, y qué porcentaje de ellos enviará datos al servidor de manera simultánea. Por ejemplo mil lectores, y que en hora pico haya hasta 500 enviando una petición al mismo tiempo, entonces necesitas estar preparado para procesar hasta 500 peticiones simultáneas. Calcula el tiempo que te tardas en procesar una petición si llega de inmediato. Suponte que fueran 250ms. Calcula también la latencia en red (el tiempo que tardan los datos en llegar del lector al server y de regreso, sin tomar en cuenta el tiempo de procesamiento en la aplicación). Suponte que fueran 500ms ida y vuelta

Ahora, cuánto es lo máximo que puede esperar un lector para obtener respuesta? Si fueran por ejemplo 10 segundos, entonces en el peor de los casos, una petición puede ser enviada al server, encolarse detrás de otras 36 o 38 peticiones, más la latencia de la red, te da casi los 10 segundos. Si esperas hasta 500 peticiones simultáneas, y máximo debes tener 38 encoladas, entonces necesitas un ThreadPool de unos 15 hilos para no tener broncas.

Ahora, esos son los hilos en el thread pool. Aparte de eso, si vas a usar HTTP porque es lo que usan los lectores, necesitas estar preparado para recibir hasta 500 peticiones, eso es en el ServerSocket y de ahí tienes que encolar las peticiones al ThreadPool. En mi blog tengo algo de eso, usando java.io y java.nio pero ahora te recomiendo java.io porque el hardware moderno está mucho mejor preparado para manejar muchos hilos, de modo que no tienes bronca con el modelo de hilo-por-petición (además que vas a usar un ThreadPool).

Tienes que mover parámetros en el sistema operativo para que tu aplicación pueda tener varios archivos abiertos. En Linux por ejemplo cada socket se maneja a nivel sistema operativo con un file descriptor, de modo que para 500 peticiones, necesitas 500 file descriptors. Si aparte tienes un pool de conexiones a base de datos, digamos de 50 conexiones, son otros 50 file descriptors. El límite de descriptors para un usuario lo ves con ulimit -n, debe estar cuando menos al cuádruple de lo que calcules necesitar (en este caso, arriba de 2048).

Yo tengo un sistema que procesa arriba de 500mil operaciones diarias, está repartido en 4 instancias de una aplicación JavaSE, aparte hay algunas aplicaciones web para administración de la información, y todo va a una base de datos en PostgreSQL. Para optimizar la base de datos contratamos a un experto que estuvo afinando parámetros y repartiendo índices y tablas en espacios distintos que fueran a particiones distintas, configuraron el RAID en el servidor (que es dedicado para PostgreSQL nada más, estamos ya con la versión 9 para tener la replicación nativa). Ahí lo que necesitas es tener buen hardware, pero PostgreSQL aguanta sin bronca 100mil peticiones diarias no tiene problema.

Para datos históricos pues depende mucho de tu aplicación. Puede convenirte un proceso en donde seguido pases datos a tablas históricas, separadas de las tablas donde guardas los movimientos generados en tiempo real. Esas tablas pueden estar en otra base de datos, en otro servidor, para que las consultas las hagas ahí y si se tardan no afecte el desempeño de la base de datos que está recibiendo datos nuevos, porque es muy importante que esa tenga la menor latencia posible.

Y para esas consultas, con buenos índices y limitando los parámetros de consulta no debes tener bronca para tener buen tiempo de respuesta.

HTTP vs Sockets

Gracias por tu respuesta ezamudio:

Cuántos lectores de tarjetas son?
Tengo al rededor de 2000 terminales, justo en este momento estoy haciendo los cálculos del tiempo máximo que podría tardar una petición en el peor de los casos (Gracias por explicarme la manera de hacer un cálculo aproximado de esta situación, me ha sido de mucha ayuda)

Ahora, cuánto es lo máximo que puede esperar un lector para obtener respuesta?
Los lectores no reciben respuesta (a menos que hubiera un error en la transacción), simplemente lanzan la petición y listo.

En mi blog tengo algo de eso, usando java.io y java.nio
Gracias, lo voy checar

Yo tengo un sistema que procesa arriba de 500mil operaciones diarias, está repartido en 4 instancias de una aplicación JavaSE,
Cuál es la ventaja de repartirlo en varias instancias?

Tengo otra duda no se si puedas ayudarme, no me convendría más utilizar un contenedor de servlets (p.e. tomcat) y hacer las operaciones desde un servlet en lugar de utilizar sockets? Qué ventajas/desventajas tiene hacerlo con este esquema?

PostgreSQL aguanta sin bronca 100mil peticiones diarias no tiene problema.
Gracias, me alivia mucho escuchar esto

Gracias por toda tu ayuda y tus consejos, un saludo

Imagen de ezamudio

instancias

Tener varias instancias de la aplicación te permite hacer balanceo de cargas, pero con 2mil terminales no es necesario. Yo tengo 4 instancias porque son 80mil terminales que usan distintas tecnologías, de modo que además de balanceo de carga puedo tener instancias dedicadas a recibir peticiones por distintos canales. Tu tienes 2mil terminales de un solo tipo, con una instancia es más que suficiente. Incluso podrías implementar el patrón hilo-por-conexión para procesar sus peticiones, o usar un ThreadPool con cache en vez de uno fijo, de modo que pueda crecer en horas pico y reducirse en periodos de baja o nula actividad.

Implementar tu propio server te permite mayor control, pero tienes que hacer más código; si las terminales tienen algún protocolo mafufo, puede ser más fácil que lo implementes por tu cuenta. Si las terminales usan HTTP, es más fácil que uses un contenedor de servlets y sólo te concentres en implementar el servlet, dejando lo demás a configuración del contenedor (número de hilos para procesar peticiones, tamaño de pool a base de datos, etc).

Bluetooth - Wireless

En realidad lo que se tiene planeado es que la terminal lectora envíe la información a través de bluetooth a un CPU muy cercano a ella (Me dicen que lo quieren hacer así para ahorrar costos y no tener la terminal siempre conectada a Internet)
Luego el CPU será quien envíe esa info que recibió de la terminal hacia el servidor a través de internet. Por todo lo que me dices, creo que la mejor y más simple alternativa es usar un servlet container para el servidor. De esta forma sólo hago una aplicación que mande al servidor (a través de una conexión HTTP) los datos que recibí por bluetooth de la terminal

Leí completo tu artículo sobre java.io y java.nio y veo que la diferencia es que java.io bloquea el hilo y java.nio no lo hace.
Mi pregunta es: Si desarrollo mi servidor con servlets, ¿Debo utilizar java.nio dentro del servlet para que no bloque al momento de escribir al outputstream (o leer del inputstream) o esto sólo aplica para cuando estas manejando sockets?.

Si las terminales usan HTTP, es más fácil que uses un contenedor de servlets y sólo te concentres en implementar el servlet, dejando lo demás a configuración del contenedor (número de hilos para procesar peticiones, tamaño de pool a base de datos, etc).
No sabía que un contenedor de servlets puede ser configurado y decirle el número de hilos que van a procesar las peticiones, esto quiere decir que con sólo mover los parámetros del tomcat (por ejemplo), ya estoy simulando un ThreadPool?

Aprecio mucho tu atención y tus respuestas, gracias

Imagen de ezamudio

threadpool

No simulas un threadpool. Cada contenedor es distinto pero por lo general tienen parámetros de configuración que puedes modificar como por ejemplo el límite de peticiones simultáneas que pueden atender, o si usan un threadpool para esas peticiones pues te dejan que le muevas los parámetros (cuántos hilos máximo, cuántos mínimo, cuánto tiempo de vida antes de tronar los hilos inactivos, etc). Igual para los pools de conexiones a base de datos.

Lo de java.nio o java.io es en caso que implementes tus propios sockets; en caso de usar servlets no necesitas preocuparte por eso en el server. Y del lado del cliente que recibe datos bluetooth y envía esos mismos datos ya via TCP, ahí sí tienes que manejar sockets pero de cliente, que son más sencillos, o si usas HTTP pues con usar HttpUrlConnection o usar el cliente HTTP de Apache.

Muchas gracias por su

Muchas gracias por su apreciable ayuda, voy a hacer algunas pruebas

Duda

Una duda ezamudio sobre algo que mencionaste:

Si esperas hasta 500 peticiones simultáneas, y máximo debes tener 38 encoladas, entonces necesitas un ThreadPool de unos 15 hilos para no tener broncas.
Entiendo el cálculo de las 38 peticiones simultaneas, pero cómo hiciste el cálculo para saber que el ThreadPool debe ser de 15 Hilos? Cada hilo atenderá 38 peticiones para hacer un total de 570?

Gracias

Imagen de bferro

RTFM: Apache Tomcat Configuration Reference

De la configuración de Tomcat:

  1. The HTTP Connector element represents a Connector component that supports the HTTP/1.1 protocol.
  2. One or more such Connectors can be configured as part of a single Service, each forwarding to the associated Engine to perform request processing and create the response.
  3. HTTP supports the following additional attributes (in addition to the common attributes listed above):
  4. .....
  5. maxThreads: The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool.
Imagen de ezamudio

cálculos

Es correcto lo que mencionas pero el cálculo lo hice alrevés. Primero estimé 500 peticiones simultáneas (este número me lo saqué del equivalente anatómico de /dev/random), luego puse lo de los 10 segundos (otro número que salió del mismo lugar), el tiempo de procesamiento en 250ms (uno más que viene de ahí) y con esos tres parámetros determiné lo demás: para procesar 500 peticiones, cada una debe estar encolada máximo 9 segundos para dar de medio segundo a un segundo de tiempo a viajar por la red, entonces se pueden encolar de 36 a 38 peticiones en un hilo. Dividimos las 500 peticiones entre 36 y nos da 13.8888 lo cual simplemente redondeé a 15.

Pero lo importante es la manera de calcular esto. Tú conoces, o deberías conocer (si no los tienes, hay que medir, o estimar o adivinar) las 3 variables de entrada: número de peticiones simultáneas, tiempo máximo de espera de una petición (bueno aunque quien espera realmente es la terminal), y tiempo de procesamiento de una petición. Sólo hay que dividir el número de peticiones simultáneas entre el número de peticiones que se pueden encolar en un hilo, lo cual se obtiene dividiendo el tiempo máximo de espera entre tiempo de procesamiento.

Imagen de iberck

Tecnología metro/metrobus

Hola a todos:

Yo tengo un problema similar pero los tiempos de respuesta que necesito son de 500 ms máximo porque se debe mostrar saldos en las terminales después de pasar por un torniquete. Sinceramente no creo alcanzar esos tiempos ya en producción guardando los datos en un servidor externo, por lo que quiero probar guardar en crédito en la tarjeta misma (como le hacen los del metrobus) y no en una BD de un servidor externo como lo quiere hacer hobo_75. (Tal vez esta sea otra alternativa para resolver tu problema)

La bronca es que no conozco mucho de tecnologías de tarjetas y máquinas lectoras, alguien sabe qué tecnología ocupan en el metro/metrubus?

Imagen de ezamudio

proveedores

Necesitas ver un proveedor de smartcards. El que yo conozco es Gemplus, tienen oficinas en México y son los que le hacen las tarjetas de telefonía pública a Telmex y creo que hasta las SIMs de celulares a Telcel. Tienen de todo tipo, hay contactless y con distintos tipos de chip, tienen su SDK donde puedes programar el firmware para el chip y creo que te pueden dar capacitación y/o consultoría en esa parte.

Imagen de iberck

Re: proveedores

Vientos enrique, gracias... Lo voy a checar