Como configurar o driver MongoDB Java MongoOptions para uso em produção?

100

Tenho pesquisado na web as melhores práticas para configurar MongoOptions para o driver Java MongoDB e não encontrei muito além da API. Esta pesquisa começou depois que encontrei o erro "com.mongodb.DBPortPool $ SemaphoresOut: Sem semáforos para obter conexão db" e, aumentando as conexões / multiplicador, consegui resolver esse problema. Estou procurando links ou suas melhores práticas na configuração dessas opções para produção.

As opções para o driver 2.4 incluem: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • connectionsPerHost
  • connectTimeout
  • maxWaitTime
  • socketTimeout
  • threadsAllowedToBlockForConnectionMultiplier

Os drivers mais novos têm mais opções e eu também gostaria de saber mais sobre elas.

Dan Polites
fonte

Respostas:

160

Atualizado para 2.9:

  • autoConnectRetry significa simplesmente que o driver tentará se reconectar automaticamente ao (s) servidor (es) após desconexões inesperadas. Em ambientes de produção, você geralmente deseja que isso seja definido como verdadeiro.

  • connectionsPerHost é a quantidade de conexões físicas que uma única instância do Mongo (é um singleton, então você geralmente tem uma por aplicativo) pode estabelecer para um processo mongod / mongos. No momento da escrita, o driver java estabelecerá essa quantidade de conexões eventualmente, mesmo se a taxa de transferência real da consulta for baixa (em palavras de ordem, você verá a estatística "conn" no mongostat aumentar até atingir esse número por servidor de aplicativo).

    Não há necessidade de definir isso para mais de 100 na maioria dos casos, mas essa configuração é uma daquelas coisas de "teste e veja". Observe que você terá que se certificar de definir isso baixo o suficiente para que a quantidade total de conexões com o seu servidor não exceda

    db.serverStatus().connections.available

    Na produção, temos atualmente 40.

  • connectTimeout . Como o nome sugere, o número de milissegundos que o driver irá esperar antes que uma tentativa de conexão seja abortada. Defina o tempo limite para algo longo (15-30 segundos), a menos que haja uma chance realista e esperada de que isso atrapalhe tentativas de conexão bem-sucedidas. Normalmente, se uma tentativa de conexão leva mais do que alguns segundos, sua infraestrutura de rede não é capaz de um alto rendimento.

  • maxWaitTime . Número de ms que um encadeamento aguardará até que uma conexão se torne disponível no pool de conexão e gerará uma exceção se isso não acontecer a tempo. Mantenha o padrão.

  • socketTimeout . Valor de tempo limite de soquete padrão. Defina para 60 segundos (60.000).

  • threadsAllowedToBlockForConnectionMultiplier . Multiplicador para connectionsPerHost que denota o número de encadeamentos que podem aguardar que as conexões se tornem disponíveis se o conjunto estiver esgotado no momento. Esta é a configuração que causará a exceção "com.mongodb.DBPortPool $ SemaphoresOut: Out of semmaphores to get db connection". Ele lançará essa exceção quando a fila de threads exceder o valor threadsAllowedToBlockForConnectionMultiplier. Por exemplo, se connectionsPerHost for 10 e esse valor for 5, até 50 threads podem ser bloqueados antes que a exceção mencionada seja lançada.

    Se você espera grandes picos na taxa de transferência que podem causar grandes filas, aumente temporariamente esse valor. No momento, temos em 1500 exatamente por esse motivo. Se a carga de sua consulta ultrapassar consistentemente o servidor, você deve apenas melhorar sua situação de hardware / dimensionamento de acordo.

  • readPreference . (ATUALIZADO, 2.8+) Usado para determinar a preferência de leitura padrão e substitui "slaveOk". Configure um ReadPreference por meio de um dos métodos de fábrica da classe. Uma descrição completa das configurações mais comuns pode ser encontrada no final desta postagem

  • w . (ATUALIZADO, 2.6+) Este valor determina a "segurança" da gravação. Quando esse valor é -1, a gravação não relatará nenhum erro, independentemente dos erros de rede ou banco de dados. WriteConcern.NONE é o WriteConcern predefinido apropriado para isso. Se w for 0, os erros de rede farão a gravação falhar, mas os erros mongo não. Isso normalmente é conhecido como gravações do tipo "disparar e esquecer" e deve ser usado quando o desempenho é mais importante do que consistência e durabilidade. Use WriteConcern.NORMAL para este modo.

    Se você definir w como 1 ou superior, a gravação é considerada segura. As gravações seguras executam a gravação e são acompanhadas por uma solicitação ao servidor para garantir que a gravação foi bem-sucedida ou recupera um valor de erro caso não tenha (em outras palavras, envia um comando getLastError () após a gravação). Observe que até que este comando getLastError () seja concluído, a conexão é reservada. Como resultado disso e do comando adicional, a taxa de transferência será significativamente menor do que as gravações com w <= 0. Com um valor aw de exatamente 1, o MongoDB garante que a gravação foi bem-sucedida (ou falhou verificadamente) na instância para a qual você enviou a gravação.

    No caso de conjuntos de réplicas, você pode usar valores mais altos para o que diz ao MongoDB para enviar a gravação para pelo menos "w" membros do conjunto de réplicas antes de retornar (ou mais precisamente, esperar pela replicação de sua gravação para membros "w" ) Você também pode definir w como a string "maioria", que informa ao MongoDB para realizar a gravação na maioria dos membros do conjunto de réplicas (WriteConcern.MAJORITY). Normalmente, você deve definir isso como 1, a menos que precise de desempenho bruto (-1 ou 0) ou gravações replicadas (> 1). Valores maiores que 1 têm um impacto considerável na taxa de transferência de gravação.

  • fsync . Opção de durabilidade que força o mongo a descarregar no disco após cada gravação, quando ativada. Eu nunca tive problemas de durabilidade relacionados a uma lista de pendências de gravação, então temos isso em falso (o padrão) na produção.

  • j * (NOVO 2.7+) *. Booleano que, quando definido como true, força o MongoDB a esperar por um commit de grupo de registro em diário bem-sucedido antes de retornar. Se o registro no diário estiver ativado, você poderá ativá-lo para obter durabilidade adicional. Consulte http://www.mongodb.org/display/DOCS/Journaling para ver o que o registro no diário oferece (e, portanto, por que você pode querer habilitar este sinalizador).

ReadPreference A classe ReadPreference permite que você configure para quais instâncias mongod as consultas são roteadas se você estiver trabalhando com conjuntos de réplicas. As seguintes opções estão disponíveis:

  • ReadPreference.primary () : todas as leituras vão apenas para o membro primário repset. Use-o se desejar que todas as consultas retornem dados consistentes (os gravados mais recentemente). Este é o padrão.

  • ReadPreference.primaryPreferred () : todas as leituras vão para o membro primário repset, se possível, mas podem consultar membros secundários se o nó primário não estiver disponível. Assim, se o primário se tornar indisponível, as leituras se tornarão eventualmente consistentes, mas apenas se o primário não estiver disponível.

  • ReadPreference.secondary () : todas as leituras vão para os membros repset secundários e o membro primário é usado apenas para gravações. Use isto apenas se você pode viver com leituras eventualmente consistentes. Membros adicionais do repset podem ser usados ​​para aumentar o desempenho de leitura, embora haja limites para a quantidade de membros (votantes) que um repset pode ter.

  • ReadPreference.secondaryPreferred () : todas as leituras vão para os membros do repset secundários se algum deles estiver disponível. O membro primário é usado exclusivamente para gravações, a menos que todos os membros secundários fiquem indisponíveis. Além do fallback para o membro primário para leituras, é o mesmo que ReadPreference.secondary ().

  • ReadPreference.nearest () : As leituras vão para o membro repset mais próximo disponível para o cliente de banco de dados. Use apenas se leituras eventualmente consistentes forem aceitáveis. O membro mais próximo é o membro com a menor latência entre o cliente e os vários membros repset. Como os membros ocupados eventualmente terão latências mais altas, isso também deve equilibrar automaticamente a carga de leitura, embora na minha experiência o secundário (Preferencial) pareça fazer isso melhor se as latências dos membros forem relativamente consistentes.

Observação: todos os itens acima têm versões ativadas por tag do mesmo método que retornam instâncias TaggableReadPreference. Uma descrição completa das tags do conjunto de réplicas pode ser encontrada aqui: Tags do conjunto de réplicas

Remon van Vliet
fonte
6
Não é perigoso deixar socketTimeout e connectTimeout como padrão (infinito)? Se uma conexão for interrompida por algum motivo, seu aplicativo (ou pelo menos aquele thread) ficará preso para sempre. Isso não deveria ser definido como muito alto (algo como 30 segundos para conectar, 2 minutos para soquete)?
Idris Mokhtarzada
Idris, é verdade. Em minha postagem, presumi erroneamente que MongoOptions tinha nossos padrões. Nossa camada Mongo ORM tem isso em 15 segundos e 1 minuto, respectivamente, e enquanto escrevia, assumi que esses eram os padrões. Tempos limite infinitos são definitivamente uma má ideia. Obrigado pelo
aviso
a opção "slaveOk" agora está obsoleta, se você quiser que o equivalente disso seja verdadeiro, faça: mongoOptions.readPreference = ReadPreference.secondaryPreferred ();
Gubatron
Boa resposta, mas sua definição de threadsAllowedToBlockForConnectionMultiplier está errada (multiplicador de palavra-chave). De acordo com os documentos: "multiplicador para connectionsPerHost para # de threads que podem bloquear se connectionsPerHost for 10 e threadsAllowedToBlockForConnectionMultiplier for 5, então 50 threads podem bloquear mais do que isso e uma exceção será lançada"
Tyler Zale
3
Parece uma resposta bastante popular. Se alguém estiver interessado em que eu atualize isso para refletir as alterações no driver mais recente, me avise
Remon van Vliet