martes, enero 17, 2012
|
Hoy quiero escribir un breve artículo para aquellos que se inician en el mundo de la informática (o incluso para aquellos ya con algunos años de experiencia pero que quizás no sabían del tema), pues es algo que toma mucha importancia a la hora de confeccionarse aplicaciones web para que escalen a miles o millones de usuarios.
El tema es qué es un Connection Pool en relación a bases de datos. Antes de iniciar debo decir que la técnica de Connection Pools es algo que antes de la Era Web por lo general era conocido solo por unos cuantos expertos en bases de datos que desarrollaban aplicaciones que debían escalar con miles de transacciones por segundo (como por ejemplo, sistemas para manejar Bolsas de Valores, Reservaciones Aéreas, etc). Recordemos que antes de la web la mayoría de los sistemas eran del tipo Cliente-Servidor (y algunos cuantos multi-tier), y por lo general para una cantidad limitada de usuarios en una LAN en donde se tenía un buen control sobre el acceso a dichas aplicaciones, y el tema de demasiadas conexiones a bases de datos no era muy problemático. Sin embargo, con la llegada de la web, cualquier página en Internet está expuesta potencialmente a decenas o cientos de miles de pedidos de usuarios simultáneos, por lo que el tema de Connection Pools toma mucha relevancia. Pero, ¿qué es Connection Pooling y cuál es el problema que resuelve, y cómo lo resuelve? Pues veamos primero el problema... Imaginen que tienen una base de datos a la cual han conectado una página web de ventas de productos, y que de repente la página se vuelve popular y los usuarios empiezan a hacer pedidos en masa. Al inicio todo estará color de rosa, pero eventualmente, conforme aumenta la demanda en la base de datos, llegaremos a un punto bastante conocido por aquellos que programan sistemas web sin conocer este tema: El famoso error de "demasiadas conexiones a la base de datos". El problema es que las bases de datos tiene un gran Talón de Aquiles del cual asombrosamente una gran cantidad de desarrolladores parece desconocer: Crear una conexión es un proceso extremadamente caro (en términos de recursos de hardware) en comparación a hacer simples queries. Ese problema no se hace evidente en la etapa de desarrollo de un sistema ya que por lo general el sistema lo desarrollan un puñado de personas, por lo que el impacto en la base de datos es mínimo. Sin embargo, en el momento que le pedimos a una base de datos (cualquier base de datos) que abra y cierre 1000 conexiones por segundo (o incluso por minuto), nos metemos en graves problemas... Pero existe una solución bastante conocida entre expertos, y es bastante simple y sumamente efectiva, y como podrán adivinar es el tema de Connection Pools, que no es ni una tecnología ni un producto, sino que más bien una técnica, que se implementa en casi cualquier entorno de programación. La idea es la siguiente: En vez de crear y destruir una conexión cada vez que un usuario la solicite, hagamos algo diferente. Vamos a mantener un grupo (o "pool") de conexiones (de ahí el nombre "Connection Pool"), con un número fijo de conexiones siempre abiertas y conectadas a la base de datos. Esas conexiones jamás se cerrarán. Eso de inicio resuelve el problema de uno tener que abrir y cerrar conexiones constantemente y aumenta el rendimiento de la base de datos tremendamente. Pero, ¿y qué pasa si se conectan más personas a la base de datos que el número de conexiones que poseemos? Pues acá entra la segunda parte de la solución que ofrece esta técnica... A simple vista aparentaría que la solución es crear más conexiones, pero eso no resuelve el problema, y al contrario, nos regresa eventualmente al mismo problema de antes, e incluso al largo plazo lo empeoraría ya que utilizaríamos tantos recursos fijos que el CPU, la memoria y el bus del servidor estarían constantemente bajo tensión hasta que la máquina se arrodille y pida piedad. Entonces, lo que se hace en realidad es que ese grupo de conexiones (que por lo general es bajo, pero depende del hardware y software de la aplicación, pero asumamos que son 20 conexiones) se recicla constantemente. Y ese reciclaje es el gran truco de esta técnica, y funciona de esta manera: Cada vez que un usuario entra en sesión con la aplicación, y desea hacer una operación que requiera de un query a la base de datos, lo que ocurre es que un Database Connection Manager (en esencia, un intermediario entre tu código y la base de datos) te presta una conexión. Cuando obtienes tu conexión prestada (en esencia, obtienes una referencia a la conexión), puedes hacer todos los queries que deseas para ese pedido en particular del cliente, pero (y esta es una parte muy importante) en el momento que termines de hacer los queries tu devuelves la conexión al Manager. El Manager en ese momento etiqueta la conexión que le devolviste como "disponible para ser prestada a alguien más", y repite el proceso. En esencia, el Manager vive en un loop infinito prestando conexiones y recibiendo conexiones devueltas, pero (y no olviden esta parte) el Manager nunca cierra esas conexiones o abre nuevas (salvo la excepción de que por diseño del Manager se creen nuevas conexiones dinámicamente para ponerlas en el pool, pero ese ya es otro tema concerniente al diseño de este tipo de objetos). Pero, ¿y por qué funciona esto de tener solo 20 conexiones recicladas mejor que el tener por ejemplo 200 conexiones constantemente abriendo y cerrando? Pues por la sencilla razón de que como les mencioné anteriormente, el abrir y cerrar conexiones es un proceso muy costoso, por lo que en la práctica es mejor reciclar 20 conexiones que abrir y cerrar 200. Sin embargo, esa no es la única razón por la cual este tipo de soluciones se utiliza mucho para escalar. Otra gran ventaja de esta técnica es que no hace que la aplicación se caiga (o que se haga mucho más difícil que caiga). Me explico a continuación... En el modelo tradicional de abrir y cerrar conexiones, en el momento que no existen más conexiones lo que sucede es que si se llega a un límite, la aplicación se tranca ya que no puede seguir más, y vemos los famosos errores de límites de conexiones, pero en el modelo de Connection Pooling, los pedidos se ponen en una cola (en esencia, un Queue tipo FIFO - el primero que entra, sale), lo que significa que si las 20 conexiones están prestadas actualmente que un nuevo pedido de un usuario por la web no causará un error, sino que simplemente una pequeña espera de unos cuantos milisegundos (o quizás algunos segundos) mientras el Manager espera que alguien más le devuelva una conexión para prestártela a ti. Esa espera se puede medir en promedio, y es a propósito una manera para en sistemas en producción uno poder afinar el valor de la cantidad de conexiones en el pool. Algo que es importante también que sepan es que hoy día la mayoría de los entornos modernos de programación (como Java Enterprise Edition, Adobe ColdFusion, el Microsoft .Net, etc) ya hacen esto tras bastidores por ti (hasta cierto punto, siendo ColdFusion quizás el mejor ejemplo en donde uno literalmente no hace nada y todo ocurre transparentemente para el programador), y es esta transparencia la razón por la cual quizás muchos desconozcan el tema, pero es bueno saber siempre lo que ocurre "tras bastidores" pues armados con este conocimiento de hoy ustedes podrán posiblemente diagnosticar en un futuro que el problema de escalabilidad sea tan sencillo como implementar un Connection Pool, o si existe uno el de disminuir o incrementar la cantidad de conexiones fijas. En nota relacionada, este artículo lo escribí debido a mi decepción de que aun con todos estos años, PHP no soporta todavía esta técnica, razón por la cual no es factible utilizarlo "de caja" para aplicaciones que necesiten escalar masivamente. Pero antes de que comenten y digan lo contrario sobre PHP, noten que la modalidad de conexión por pconnection en realidad no es lo mismo que esto, ya que no soporta transacciones ACID debido a una limitación de PHP mismo, por lo que en la práctica solo es útil para hacer lecturas a bases de datos y no escrituras. Así mismo Oracle tiene una manera de implementar Connection Pools con su base de datos, pero es propietaria y requiere modificar el código estándar de PHP para que funcione. Y si preguntan de empresas como Facebook, Google, Yahoo y Amazon que utilizan PHP de alguna forma u otra, estas empresas también debieron romper con la estandarización de PHP para crear sus propias soluciones de Connection Pools y poder hacer escalar a PHP. En cuanto a soluciones NoSQL, lamentablemente aun no existe estandarización, por lo que por ese lado también estamos en el aire con PHP. Mientras tanto sin embargo, prácticamente toda otra plataforma moderna de programación web soporta esta metodología, por lo que no olviden leer al respecto en sus plataformas de programación favoritas y de cómo tomar ventaja de ellas... Actualización: Quiero agregar que esta técnica de reutilizar una conexión en realidad es un patrón de programación más generalizado que el ejemplo de Connection Pools. En términos generales, un Connection Pool sería un sub-conjunto de un "Object Pool". En un Object Pool, uno pre-instancia un grupo de objetos y después con un Object Manager (por lo general, siguiendo el patrón del Singleton) uno toma prestado y devuelve objetos al pool. Esto es tan útil en cualquier dominio como lo es con bases de datos, ya que el instanciar objetos en cualquier lenguaje de programación es también un proceso costoso en términos de recursos de la máquina, mientras que tomar prestado un objeto no es más que pasar un objeto por referencia, que ocurre prácticamente de forma instantánea. Esto es de especial utilidad para desarrolladores de video-juegos, que por lo general tiene código muy compacto y optimizado, y requieren del mayor rendimiento posible. autor: josé elías |
35 comentarios |
Educación , Pregunta a eliax , Software |
Comentarios
gracias, el tema es genial ya que habla del rendimiento. Pero me preguntaba, si llegara a crear una apliacion con Connection Pool, Existen tecnicas o herramientas con las que la puedan poner a prueba?? Hola, fascinado con este articulo, ya que estoy estudiando el implementar una tiendecita online y estoy comenzando a estudiar prgramación php básica para hacer una web dinamica. Sé que hay varias webs que venden plantillas ya preparadas, pero como tu indicas a mi personalmente tambien me interesa saber que ocurre tras bastidores. Sería interesante que pudieses sacar de tu ajustado tiempo una sección dedicada a truquillos de programación. Un Saludo. Yo también conozco algún experto de SQL que desconoce los pools. Pero no siempre va ligado el SQL a la programación. Existe mucha gente que simplemente se sienta delante de una aplicación cliente a lanzar sus sentencias SQL para interactuar con la base de datos. Para ellos es transparente lo que dicha aplicación hace para comunicarse con la base de datos, su labor no es crear esas conexiones, simplemente introducir o extraer información de la base de datos a través del SQL, no es necesario que tenga dicho conocimiento, su conocimiento tiene que basarse en crear sentencias SQL óptimas para que el rendimiento de la base de datos no se vea mermado. Ahora... si una persona se dedica a programar accesos a la base de datos y desconoce los pools de conexiones, esa persona nunca se le puede considerar experto. No creo tener respuesta a tu pregunta, pero abro un poco el tema a ver si la gente se anima y aprendo yo también :) que el pooling en php de mysql suele ser el primer cuello de botella de rendimiento! Debido a cómo trabaja Apache, un pool de conexiones con php no parece tener mucho sentido, debido a la arquitectura, salvo que quieras hacer un pool en el mismo hilo y sus subhilos. En este caso singletons u otra cosa por el estilo. Por lo poco que sé, se suele desplazar este problema al servidor como hace Oracle con su DRCP o utilizar algo intermedio tipo memcached o algún msyql proxy. También se puede cambiar a fastCGI con php ya que mantiene el proceso en memoria. Un par de links interesantes sobre rendimiento asociado a LAMP: http://www.mysqlperformanceblog.com/2006/11/12/are-php-persistent-connections-evil/ http://andigutmans.blogspot.com/2006/10/php-and-database-connection-pooling.html http://highscalability.com/bunch-great-strategies-using-memcached-and-mysql-better-together Solución de oracle: http://blogs.oracle.com/opal/entry/highly_scalable_connection_poo hola, gracias por el articulo, tengo la siguiente duda, si un pool de conexiones se detiene, mediante codigo, o se muere por alguna razon, que sucede con las transacciones en el? se eliminan, se preservan hasta que vuelva a estar disponible? se realiza un rollback cuando esto pasa? gracias de antemano
Simplemente Gracias, Mi líder de proyecto me mando este enlace con el asunto: Bonita definición sobre un Pool Connection. Gracias! Añadir Comentario |
"Puedo decir que este blog abrio mi mente a un universo mucho mas grande y hermoso. Gracias."
en camino a la singularidad...
©2005-2024 josé c. elías
todos los derechos reservados
como compartir los artículos de eliax
Seguir a @eliax
Gracias Eliax tu explicación fue muy fácil de entender, ahora me siento que se un poco más que ayer! Enhorabuena por el blog.