Antes de empezar, me gustaría apuntarte un blog de mi colega Michael Nitschinger, en el que puedes aprender sobre la mejor manera de configurar tu entorno básico PHP y Couchbase, si no usas nginx & PHP-FPM:
https://nitschinger.at/Getting-Started-with-Couchbase-and-PHP
Recientemente, hemos visto mucha gente usando el SDK PHP de Couchbase junto con nginx y php-FPM. Ha habido, sin embargo, algunos problemas recurrentes entre estos usuarios, que me propongo solucionar en este artículo.
El problema que puedes estar experimentando es que no eres capaz de controlar el número de conexiones realizadas, a través de FPM a Couchbase; Estás a merced del número de procesos hijo de PHP. El hecho es que en FPM no necesitas tantas conexiones a Couchbase como procesos tengas.
Notarás un gran impacto en el rendimiento. Digamos que tenemos nuestro FPM max_children configurado a 300; bajo carga, tendrás 300 procesos PHP corriendo, y cada uno de ellos puede tener 4 instancias persistentes de CouchbaseClient. En 16 máquinas, esto son casi 20.000 objetos cliente. Estos múltiples procesos FPM paralelos no pueden compartir 1 conexión Couchbase, y este es nuestro principal problema. Nuestro otro problema es que una vez que se alcanzan los 300 procesos, estas conexiones serán eliminadas y reiniciadas. Esto es caro y algo que deberíamos desear evitar.
Retrocedamos un poco y volvamos a la raíz del problema. Nuestros Clientes Inteligentes de Couchbase mantienen una conexión abierta al gestor REST del cluster; para ser notificados sobre cambios en la topología. Esto funciona bien para la mayoría de lenguajes en los que típicamente usaríamos un número limitado de procesos, y quizás sólo 2-3 objetos en cada uno de ellos; de modo que cada servidor probablemente sólo tendría 5 de estas conexiones al cluster. Sin embargo, en un despliegue de PHP con FPM - la gente suele hacer girar alrededor de 2000 de estos procesos y si sólo utiliza _UN_ objeto Couchbase en cada uno de ellos, cada servidor ocupará entonces 2k de conexiones a nuestro servidor REST.
Sin embargo, hay un par de maneras de resolver estos problemas. Una de ellas es utilizar la función Caché de configuración de Couchbase (Disponible en el SDK de PHP v1.1.5 +). Cuando se utiliza config_cache, al crear una nueva instancia de cliente primero se busca una versión en caché de la configuración del clúster; si se encuentra, entonces no se consulta el nodo en absoluto para la configuración, sólo se utiliza el valor en caché. Si no puede conectarse a través de una configuración en caché, sólo entonces abrirá una conexión (en el puerto 8091, hablando HTTP) a uno de los nodos Couchbase que pases al constructor en tu código.
El config_cache es una ruta opcional a un directorio donde la biblioteca puede almacenar los archivos que contienen la topología del clúster. (Se utiliza para almacenar en caché la configuración en lugar de conectarse al servidor REST cada vez para descargarla). Puede habilitar la caché de conexión poniendo la siguiente línea en su Couchbase.ini file:
couchbase.config_cache = "/RUTA/AL/ALGUNO/DIRECTORIO"
Puede obtener más información sobre la caché de configuración aquí: https://www.couchbase.com/wiki/display/couchbase/libcouchbase+configuration+cache
Utilizando el Config_Cache, podemos eliminar aproximadamente ¾ de las conexiones que se habrían realizado, ahorrando recursos y solucionando en parte el problema. Las conexiones persistentes también se comparten más, así que eso puede proporcionar algo más de eficiencia. También podemos cambiar la configuración del FPM para que no ejecute tantos procesos paralelos reduciendo el max_children y aumentando el max_requests. Sugiero que intentemos ajustar el valor de pm.max_requests de 300 a 3000 o 5000 (dependiendo del tipo de sobrecarga de memoria que veamos en nuestros procesos PHP a lo largo del tiempo), lo que también reducirá el número de veces que estos objetos cliente tienen que ser recreados. También podemos reducir el número de pm.max_children a 100 más o menos.
Echa un vistazo a mi archivo de ejemplo FPM.conf como referencia: https://gist.github.com/rbin/82e47f7f75f2072f02fd