Antes de começarmos, gostaria de indicar um blog do meu colega Michael Nitschinger, no qual você pode aprender sobre a melhor maneira de configurar seu ambiente básico de PHP e Couchbase, se não estiver usando nginx e PHP-FPM:
http://nitschinger.at/Getting-Started-with-Couchbase-and-PHP
Recentemente, temos visto muitas pessoas usando o SDK PHP do Couchbase junto com o nginx e o php-FPM. No entanto, tem havido alguns problemas recorrentes entre esses usuários, que pretendo solucionar neste artigo!
O problema que você pode estar enfrentando é que não é possível controlar o número de conexões feitas pelo FPM com o Couchbase; você está à mercê do número de processos filhos do PHP. O fato é que, no FPM, você não precisa de tantas conexões com o Couchbase quanto tem processos.
Você perceberá um enorme impacto no desempenho. Digamos que nosso FPM max_children esteja definido como 300; sob carga, você terá 300 processos PHP em execução, e cada um deles pode ter 4 instâncias persistentes do CouchbaseClient. Em 16 máquinas, isso representa quase 20.000 objetos clientes. Esses vários processos FPM paralelos não podem compartilhar uma conexão com o Couchbase, e esse é o nosso principal problema. Nosso outro problema é que, uma vez atingidos 300 processos, essas conexões serão derrubadas e reiniciadas. Isso é caro e é algo que queremos evitar.
Vamos nos distanciar um pouco e voltar à raiz do problema. Nossos clientes inteligentes do Couchbase mantêm uma conexão aberta com o gerenciador REST do cluster para serem notificados sobre alterações na topologia. Isso funciona bem para a maioria das linguagens em que normalmente usamos um número limitado de processos e talvez apenas 2 a 3 objetos em cada um deles, de modo que cada servidor provavelmente teria apenas 5 conexões desse tipo com o cluster. No entanto, em uma implementação de PHP com FPM, as pessoas normalmente criam cerca de 2.000 desses processos e, se você usar apenas _UM_ objeto do Couchbase em cada um deles, cada servidor ocupará 2.000 conexões com o nosso servidor REST.
No entanto, há algumas maneiras de resolver esses problemas. Uma maneira é usar o Cache de configuração do Couchbase (Disponível no PHP SDK v1.1.5 +). Ao usar o config_cache, a criação de uma nova instância de cliente procura primeiro uma versão em cache da configuração do cluster; se ela for encontrada, o nó não será consultado para obter a configuração, apenas será usado o valor em cache. Se não for possível conectar-se por meio de uma configuração em cache, somente então ele abrirá uma conexão (na porta 8091, falando HTTP) com um dos nós do Couchbase que você passar para o construtor em seu código.
O config_cache é um caminho opcional para um diretório em que a biblioteca pode armazenar arquivos que contêm a topologia do cluster. (Usado para armazenar em cache a configuração em vez de se conectar ao servidor REST todas as vezes para fazer o download). Você pode ativar o cache de conexão colocando a seguinte linha em seu arquivo Couchbase.ini file:
couchbase.config_cache = "/CAMINHO/PARA/ALGUM/DIRETÓRIO"
Você pode ler mais sobre o Config Cache aqui: http://www.couchbase.com/wiki/display/couchbase/libcouchbase+configuration+cache
Ao utilizar o Config_Cache, podemos remover cerca de ¾ das conexões que teriam sido feitas, economizando recursos e corrigindo parcialmente o problema. As conexões persistentes também são mais compartilhadas, o que pode proporcionar um pouco mais de eficiência. Também podemos alterar a configuração do FPM para não executar tantos processos paralelos, reduzindo o max_children e aumentando o max_requests. Sugiro que tentemos ajustar o valor de pm.max_requests de 300 para 3000 ou 5000 (dependendo do tipo de inchaço de memória que você vê em seus processos PHP ao longo do tempo), o que também reduzirá o número de vezes que esses objetos do cliente precisam ser recriados. Também podemos reduzir o número de pm.max_children para 100 ou mais.
Dê uma olhada no meu exemplo de arquivo FPM.conf para referência: https://gist.github.com/rbin/82e47f7f75f2072f02fd