Estoy creando algunos servicios web que tendrían 2000 usuarios concurrentes. Los servicios se ofrecen de forma gratuita y, por lo tanto, se espera que obtengan una gran base de usuarios. En el futuro, puede ser necesario escalar hasta 50,000 usuarios.
Ya hay algunas otras preguntas que abordan el problema, como: /programming/2567254/building-highly-scalable-web-services
Sin embargo, mis requisitos difieren de la pregunta anterior.
Por ejemplo: mi aplicación no tiene una interfaz de usuario, por lo que las imágenes, CSS y JavaScript no son un problema. Está en Java, por lo que sugerencias como usar HipHop para traducir PHP a código nativo son inútiles.
Por eso decidí hacer mi pregunta por separado.
Esta es la configuración de mi proyecto:
- Descanse servicios web basados en Apache CXF
- Hibernate 3.0 (con optimizaciones relevantes como carga lenta y HQL personalizado para afinar)
- Tomcat 6.0
- MySql 5.5
¿Cuáles son las mejores prácticas a seguir para que una aplicación basada en Java sea escalable?
fuente
Respuestas:
Me ocupé del problema en el pasado, pero aún siento que tengo mucho que aprender en el campo. Considero que este es uno de los campos más interesantes que hay en el desarrollo de software hoy en día, aquí hay algunas ideas al respecto:
MySQL es una base de datos bastante justa a menos que esté trabajando con una gran cantidad de datos, y en este caso podría considerar NoSQL base de datos, pero debe examinar cuidadosamente cuál es la mejor base de datos NoSQL para sus necesidades.
Debe implementar el almacenamiento en caché en su sistema; intente almacenar en caché la mayor cantidad de datos de solo lectura tanto como sea posible, o defina algunas estrategias de almacenamiento en caché; por ejemplo, tuvimos un escenario en el que era válido para un usuario ver "datos antiguos" como siempre y cuando la actualización reciente haya tenido lugar en la última hora.
Consideraría JBoss Cache, o tal vez Infinispan (que es más como una estructura de datos distribuidos) u otro marco de almacenamiento en caché popular para esto.
Además, como mencionó tomcat, supongo que trabaja en algún módulo de solicitud-respuesta. Intente considerar el uso de un caché que existe en el alcance de una solicitud dada, esto puede ser incluso un simple HashMap que está asociado con el almacenamiento local de subprocesos .
Mi idea aquí se parece bastante al caché de primer nivel en Hibernate .
Debe recordar que los archivos, las transacciones y otros recursos son caros en términos de mantenerlos abiertos. Asegúrese de cerrar los archivos y las transacciones lo antes posible, o terminará con errores que se reproducirán en configuraciones a gran escala
Además, debe comprender qué 2000 usuarios simultáneos, ¿significa esto que 2000 usuarios están accediendo a su servidor a la vez o están utilizando su sistema? Distinga entre los casos en que 2000 usuarios intentan abrir un socket a su servidor, y un caso en el que solo 500 están, y 1500 actualmente están buscando resultados, de completar la entrada en el lado del cliente.
Debe considerar el uso de la agrupación en clúster: tendrá que lidiar con problemas como el equilibrio de carga , la sesión fija (lo que significa que el equilibrador de carga redirigirá una solicitud al mismo servidor para la misma sesión) y más.
Si necesita tener un código de sincronización, elija cuidadosamente la estrategia de sincronización. Vi algunos sistemas en los que se usaba un bloqueo simple, pero un ReaderWriterLockpodría haber mejorado las cosas, ya que la mayoría del acceso era de solo lectura.
Considere tener el almacenamiento en caché y la validación del lado del cliente si es posible, intente guardar las llamadas al servidor y enviar solo diferencias de datos, en caso de que la mayor parte de su respuesta a una solicitud con el mismo parámetro no cambie.
Por ejemplo, en el proyecto de código abierto oVirt solicitamos obtener estadísticas de una máquina virtual determinada. algunos de los datos de la máquina virtual rara vez cambian, por lo que enviamos solo MD5, si los datos cambian, el valor de MD5 también cambia, realizamos una solicitud para obtener los datos completos, y no solo el MD5.
Mencioné hibernate antes, le recomendaría que considere usarlo cuidadosamente, si necesita realizar muchas escrituras y menos lecturas, Hibernate podría no ser ideal para usted, y debería considerar trabajar con Spring-JDBC como envoltorio JDBC
Indexe su base de datos sabiamente y use un esquema de base de datos correcto. Considere usar una capa de procedimientos almacenados ya que están precompilados y optimizados.
Me gustaría decir que en el pasado, traté con un sistema (nodo único) en mysql (principalmente acceso de solo lectura) con jboss 4.2.1 y logré llegar a 2000 concurrentes los usuarios
(no accediendo a la vez en términos de abrir 2000 sockets contra nuestro servidor), pero usando / navegando en nuestro sistema, usando JBoss Cache y precargando en la caché algunos de los datos más accedidos, o datos que nos dimos cuenta que serán "populares y populares" "pero nuestra solución fue buena para nuestra arquitectura y nuestros flujos,
por lo que , como digo en estos casos,
hay más consejos y trucos, pero realmente depende de su arquitectura y de los flujos que necesita tener en su sistema". ¡Buena suerte!
fuente
Buena pregunta. Probablemente sea difícil decir cuál es el mejor enfoque, pero lo intentaré desde mi experiencia.
La mejor manera de escalar la aplicación web basada en Java es escribirla lo más sin estado posible (si es posible). Esto le permite escalar horizontalmente la aplicación, donde puede agregar servidores tomcat si hay más usuarios concurrentes.
Sin embargo, como notó, podría haber problemas con las conexiones de la base de datos. Pero la pregunta que tengo es, ¿cómo está obteniendo los datos? ¿Es generado por el usuario o usted obtiene los datos de un tercero? Esto es muy importante porque, si está prestando un servicio a su usuario con los datos agregados de una aplicación de terceros (por ejemplo, FB, Twitter, etc.), lo que puede seguir es escribir en la base de datos maestra y replicar los datos en bases de datos esclavas que se asignan a cada instancia de tomcat. Entonces cada servidor Tomcat puede obtener de su propia base de datos esclava.
Puede optar por el clúster MySQL que tiene un almacén de datos en memoria. Pero tenga cuidado con el hecho de que la aplicación puede necesitar algunos cambios. No
sql joins
están bien soportados en el clúster MySQL, aunque en la última versión hay mejoras para el mismo. Si el costo no es un factor, puede probar Oracle.La solución de almacenamiento en caché definitivamente mejorará el rendimiento. Pero entonces, todo depende de la arquitectura de toda la aplicación. Debe saber cuándo insertar datos en la memoria caché, cuándo ensuciarlos (eliminar de la memoria caché).
Con respecto a la distribución de la carga en un entorno multiservidor, le sugiero que use un equilibrador de carga que usar Apache para el equilibrio de carga.
fuente
Actualmente estoy configurando un sistema similar (a nivel profesional) y este es el diseño que he elegido:
Esto logrará una solución redundante, de alta disponibilidad y escalable.
Los equilibradores de carga (en hardware decente) equilibrarán fácilmente una línea saturada de 1 gbit cada uno. Este también es un gran lugar para la descarga de SSL.
Puede guardar la información de su sesión en memcached. En caso de que una instancia de tomcat falle, otra instancia de tomcat puede recuperar información relevante de la sesión y los clientes no notarán nada. No olvides combinar esto con sesiones adhesivas también. (Para mantener el tráfico de red bajo)
El clúster de Tomcat también tiene una opción para compartir información de sesión entre el clúster en tiempo real, sin usar memcached. Aunque creo que el rendimiento es inteligente, usar Memcached será mejor.
Si necesita más potencia en cualquiera de estas aplicaciones:
No sé cómo se compila su aplicación y cuáles son los grandes recursos de recursos, pero si ve una gran carga de base de datos (¡durante sus pruebas de carga!), Agregar un caché entre la aplicación y la base de datos ciertamente podría mejorar mucho el rendimiento. Pero no olvide que no todo es almacenable en caché, si sus consultas son siempre diferentes, el almacenamiento en caché no ayudará (mucho)
Mi consejo sería descargar VMware Workbench (o un software de virtualización similar) e intentar crear una configuración simple. Sin equilibrio de carga ni agrupamiento, solo lo básico y el trabajo a partir de ahí. Una por una, agregue más funciones (equilibrio, almacenamiento en caché, agrupamiento, etc.) y asegúrese de investigar un poco sobre cada tema, para que sepa que ha elegido correctamente.
Si sigue ejecutando las mismas pruebas de rendimiento durante este proceso, puede ver por sí mismo si usar X es mejor que usar Y en su configuración, o qué impacto tendrá el almacenamiento en caché, etc.
Al final, una configuración como esta realmente depende de los requisitos de su aplicación y sus clientes, todo se puede hacer de varias maneras, cada una con sus propias fortalezas y debilidades.
¿Alguna pregunta más?
¡Buena suerte!
Wesley
fuente