Comment configurer le pilote Java MongoDB MongoOptions pour une utilisation en production?

100

J'ai recherché sur le Web les meilleures pratiques pour configurer MongoOptions pour le pilote MongoDB Java et je n'ai pas proposé grand chose d'autre que l'API. Cette recherche a commencé après que j'ai rencontré l'erreur "com.mongodb.DBPortPool $ SemaphoresOut: Out of semaphores to get db connection" et en augmentant les connexions / multiplicateur, j'ai pu résoudre ce problème. Je recherche des liens ou vos meilleures pratiques pour configurer ces options pour la production.

Les options du pilote 2.4 incluent: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

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

Les nouveaux pilotes ont plus d'options et je serais intéressé à en entendre parler également.

Dan Polites
la source

Réponses:

160

Mis à jour à 2.9:

  • autoConnectRetry signifie simplement que le pilote tentera automatiquement de se reconnecter au (x) serveur (s) après des déconnexions inattendues. Dans les environnements de production, vous voulez généralement que ce paramètre soit défini sur true.

  • connectionsPerHost sont le nombre de connexions physiques qu'une seule instance Mongo (c'est un singleton donc vous en avez généralement une par application) peut établir avec un processus mongod / mongos. Au moment de l'écriture, le pilote java établira éventuellement ce nombre de connexions même si le débit de requête réel est faible (dans l'ordre des mots, vous verrez la statistique "conn" dans mongostat augmenter jusqu'à ce qu'elle atteigne ce nombre par serveur d'application).

    Il n'est pas nécessaire de définir ce paramètre supérieur à 100 dans la plupart des cas, mais ce paramètre est l'un de ces éléments "testez-le et voyez". Notez que vous devrez vous assurer de définir ce paramètre suffisamment bas pour que le nombre total de connexions à votre serveur ne dépasse pas

    db.serverStatus().connections.available

    En production, nous en avons actuellement 40.

  • connectTimeout . Comme son nom l'indique, le pilote attendra avant qu'une tentative de connexion ne soit interrompue. Définissez le délai d'expiration sur quelque chose de long (15-30 secondes) à moins qu'il n'y ait une chance réaliste et attendue que cela gêne les tentatives de connexion réussies. Normalement, si une tentative de connexion prend plus de quelques secondes, votre infrastructure réseau n'est pas capable d'un débit élevé.

  • maxWaitTime . Nombre de ms pendant lequel un thread attendra qu'une connexion devienne disponible sur le pool de connexions et lève une exception si cela ne se produit pas à temps. Conserver la valeur par défaut.

  • socketTimeout . Valeur de délai d'expiration standard du socket. Réglez sur 60 secondes (60000).

  • threadsAllowedToBlockForConnectionMultiplier . Multiplicateur pour connectionsPerHost qui indique le nombre de threads qui sont autorisés à attendre que les connexions deviennent disponibles si le pool est actuellement épuisé. C'est le paramètre qui provoquera l'exception "com.mongodb.DBPortPool $ SemaphoresOut: Out of semaphores to get db connection". Il lèvera cette exception une fois que cette file d'attente de threads dépassera la valeur threadsAllowedToBlockForConnectionMultiplier. Par exemple, si connectionsPerHost vaut 10 et que cette valeur est 5, jusqu'à 50 threads peuvent se bloquer avant que l'exception susmentionnée ne soit levée.

    Si vous prévoyez de gros pics de débit qui pourraient entraîner de grandes files d'attente, augmentez temporairement cette valeur. Nous l'avons à 1500 pour le moment exactement pour cette raison. Si la charge de votre requête dépasse systématiquement le serveur, vous devez simplement améliorer votre situation matérielle / évolutive en conséquence.

  • readPreference . (UPDATED, 2.8+) Utilisé pour déterminer la préférence de lecture par défaut et remplace «slaveOk». Configurez un ReadPreference via l'une des méthodes de fabrique de classes. Une description complète des paramètres les plus courants se trouve à la fin de cet article

  • w . (UPDATED, 2.6+) Cette valeur détermine la "sécurité" de l'écriture. Lorsque cette valeur est -1, l'écriture ne signalera aucune erreur, quelles que soient les erreurs de réseau ou de base de données. WriteConcern.NONE est le WriteConcern prédéfini approprié pour cela. Si w est égal à 0, les erreurs réseau feront échouer l'écriture, mais pas les erreurs mongo. Ceci est généralement appelé écrit «feu et oublie» et doit être utilisé lorsque les performances sont plus importantes que la cohérence et la durabilité. Utilisez WriteConcern.NORMAL pour ce mode.

    Si vous définissez w sur 1 ou plus, l'écriture est considérée comme sûre. Les écritures sécurisées effectuent l'écriture et le suivent par une requête au serveur pour s'assurer que l'écriture a réussi ou récupèrent une valeur d'erreur si ce n'est pas le cas (en d'autres termes, il envoie une commande getLastError () après l'écriture). Notez que tant que cette commande getLastError () n'est pas terminée, la connexion est réservée. En conséquence de cela et de la commande supplémentaire, le débit sera nettement inférieur à celui des écritures avec w <= 0. Avec une valeur aw d'exactement 1, MongoDB garantit que l'écriture a réussi (ou a échoué de manière vérifiable) sur l'instance à laquelle vous avez envoyé l'écriture.

    Dans le cas des jeux de répliques, vous pouvez utiliser des valeurs plus élevées pour w qui indiquent à MongoDB d'envoyer l'écriture à au moins "w" membres du jeu de répliques avant de retourner (ou plus précisément, attendre la réplication de votre écriture aux membres "w" ). Vous pouvez également définir w sur la chaîne "majorité" qui indique à MongoDB d'effectuer l'écriture sur la majorité des membres du jeu de réplicas (WriteConcern.MAJORITY). En règle générale, vous devez définir ce paramètre sur 1, sauf si vous avez besoin de performances brutes (-1 ou 0) ou d'écritures répliquées (> 1). Les valeurs supérieures à 1 ont un impact considérable sur le débit d'écriture.

  • fsync . Option de durabilité qui force mongo à se vider sur le disque après chaque écriture lorsqu'elle est activée. Je n'ai jamais eu de problèmes de durabilité liés à un backlog d'écriture, donc nous l'avons sur false (par défaut) en production.

  • j * (NOUVEAU 2.7+) *. Boolean qui, lorsqu'il est défini sur true, force MongoDB à attendre une validation de groupe de journalisation réussie avant de revenir. Si la journalisation est activée, vous pouvez l'activer pour une durabilité supplémentaire. Reportez-vous à http://www.mongodb.org/display/DOCS/Journaling pour voir ce que la journalisation vous apporte (et donc pourquoi vous voudrez peut-être activer cet indicateur).

ReadPreference La classe ReadPreference vous permet de configurer vers quelles instances mongod les requêtes sont acheminées si vous travaillez avec des jeux de réplicas. Les options suivantes sont disponibles:

  • ReadPreference.primary () : Toutes les lectures vont uniquement au membre principal du repset. Utilisez cette option si vous souhaitez que toutes les requêtes renvoient des données cohérentes (les plus récemment écrites). C'est la valeur par défaut.

  • ReadPreference.primaryPreferred () : Toutes les lectures vont au membre principal de repset si possible mais peuvent interroger les membres secondaires si le nœud principal n'est pas disponible. En tant que tel, si le primaire devient indisponible, les lectures deviennent finalement cohérentes, mais uniquement si le primaire n'est pas disponible.

  • ReadPreference.secondary () : toutes les lectures vont aux membres du repset secondaire et le membre principal est utilisé pour les écritures uniquement. Utilisez ceci uniquement si vous pouvez vivre avec des lectures finalement cohérentes. Des membres de répétition supplémentaires peuvent être utilisés pour augmenter les performances de lecture, bien qu'il y ait des limites au nombre de membres (votants) qu'un répétition peut avoir.

  • ReadPreference.secondaryPreferred () : toutes les lectures vont aux membres du repset secondaire si l'un d'entre eux est disponible. Le membre principal est utilisé exclusivement pour les écritures, sauf si tous les membres secondaires deviennent indisponibles. À part le retour au membre principal pour les lectures, c'est le même que ReadPreference.secondary ().

  • ReadPreference.nearest () : les lectures vont au membre repset le plus proche disponible pour le client de base de données. À n'utiliser que si des lectures finalement cohérentes sont acceptables. Le membre le plus proche est le membre avec la latence la plus faible entre le client et les différents membres du repset. Étant donné que les membres occupés auront éventuellement des latences plus élevées, cela devrait également équilibrer automatiquement la charge de lecture, bien que d'après mon expérience, secondaire (Preferred) semble le faire mieux si les latences des membres sont relativement cohérentes.

Remarque: Tous les éléments ci-dessus ont des versions activées pour les balises de la même méthode qui renvoient des instances TaggableReadPreference à la place. Une description complète des balises de jeu de répliques peut être trouvée ici: Balises de jeu de répliques

Remon van Vliet
la source
6
N'est-il pas dangereux de laisser socketTimeout et connectTimeout par défaut (infini)? Si une connexion se bloque pour une raison quelconque, votre application (ou du moins ce thread) restera bloquée pour toujours. Ne devraient-ils pas simplement être définis comme très très élevés (quelque chose comme 30 secondes pour la connexion, 2 minutes pour la prise)?
Idris Mokhtarzada
Idris, très vrai. Dans mon article, j'ai supposé à tort que MongoOptions avait nos valeurs par défaut. Notre couche Mongo ORM les a respectivement à 15 secondes et 1 minute et en écrivant, j'ai supposé qu'il s'agissait des valeurs par défaut. Les délais d'attente infinis sont définitivement une mauvaise idée. Merci pour le heads up, je l'ai corrigé dans le post
Remon van Vliet
l'option "slaveOk" est maintenant obsolète, si vous voulez que l'équivalent de ceci soit vrai, faites: mongoOptions.readPreference = ReadPreference.secondaryPreferred ();
Gubatron
Bonne réponse mais votre définition de threadsAllowedToBlockForConnectionMultiplier est fausse (multiplicateur de mot-clé). Selon la documentation: "multiplicateur pour connectionsPerHost pour # de threads qui peuvent bloquer si connectionsPerHost vaut 10, et threadsAllowedToBlockForConnectionMultiplier vaut 5, alors 50 threads peuvent bloquer plus que cela et une exception sera lancée"
Tyler Zale
3
Semble une réponse assez populaire. Si quelqu'un est intéressé par ma mise à jour pour refléter les changements dans le dernier pilote, faites le moi savoir
Remon van Vliet