2011-02-09 4 views
6

J'ai une servlet Java qui est surchargée par les demandes des clients pendant les heures de pointe. Certains clients couvrent des demandes simultanées. Parfois, le nombre de demandes par seconde est tout simplement trop élevé. Dois-je mettre en œuvre une logique d'application pour limiter le nombre de requêtes que le client peut envoyer par seconde? Est-ce que cela doit être fait au niveau de l'application?Empêcher le client de surcharger le serveur?

+3

Ajoutez plus de matériel. –

+0

Tant que toutes les demandes sont valides, je suis d'accord avec Anon, j'y ajoute plus de matériel (plus facile) ou j'optimise votre servlet Java. Si les demandes sont comme des spams, vous pouvez les bloquer à un niveau inférieur en utilisant quelque chose comme iptables ou un bloc de niveau apache – Nick

+1

Sa question est valide. Il peut toujours y avoir plus de demandes que le matériel ne peut gérer. Un serveur a besoin d'un moyen de limiter les requêtes et de faire tomber le système pendant les charges excessives. –

Répondre

1

Les deux manières les plus courantes de gérer cela sont de refuser des demandes lorsque le serveur est trop occupé ou de gérer chaque requête plus lentement.

Il est facile de refuser des demandes; il suffit de lancer un nombre fixe d'instances. Le système d'exploitation peut ou non mettre en file d'attente quelques demandes de connexion, mais en général, les utilisateurs ne peuvent tout simplement pas se connecter. Une manière plus gracieuse de le faire est de demander au service de renvoyer un code d'erreur indiquant que le client devrait réessayer plus tard.

La gestion des requêtes plus lentes est un peu plus laborieuse, car elle nécessite de séparer la servlet gérant les requêtes de la classe effectuant le travail dans un thread différent. Vous pouvez avoir un plus grand nombre de servlets que les ouvrières. Lorsqu'une requête arrive, elle l'accepte, attend un ouvrier, l'attrape et l'utilise, le libère, puis renvoie les résultats.

Les deux peuvent communiquer à travers l'une des classes java.util.concurrent, comme LinkedBlockingQueue ou ThreadPoolExecutor. Si vous voulez avoir vraiment envie, vous pouvez utiliser quelque chose comme un PriorityBlockingQueue pour servir certains clients avant les autres.

Moi, je jetterais plus de matériel à elle comme Anon dit;)

1

Quelques réponses solides ici. Je pense que plus de matériel est le chemin à parcourir. Avoir trop de clients ou de trafic est habituellement un bon problème à avoir. Toutefois, si vous devez impérativement limiter les clients, vous avez le choix entre plusieurs options.

Les solutions les plus évolutives que j'ai vues tournent autour d'un système de mise en cache distribué, comme Memcached, et utilisent des entiers pour garder les comptes.

Déterminez la vitesse à laquelle votre système peut gérer le trafic. Soit globalement, soit par client. Ensuite, mettez un compte dans memcached qui représente ce taux. Chaque fois que vous obtenez une requête, décrémentez la valeur. Incrémenter périodiquement le compteur pour permettre plus de trafic à travers. Par exemple, si vous pouvez gérer 10 demandes/seconde, faites un compte de 50 toutes les 5 secondes, jusqu'à un maximum de 50. De cette façon, vous ne le remplissez pas tout le temps, mais vous pouvez également gérer un peu d'éclatement limité à une fenêtre. Vous devrez expérimenter pour trouver un bon taux de rafraîchissement. La clé de ce compteur peut être soit une clé globale, soit basée sur l'identifiant de l'utilisateur si vous avez besoin de restreindre cette manière. La bonne chose à propos de ce système est qu'il fonctionne sur un cluster entier ET que le mécanisme qui remplit les compteurs n'est pas nécessairement dans l'un de vos serveurs actuels. Vous pouvez dédier un processus séparé pour cela. Les serveurs chargés ont seulement besoin de le vérifier et de le décrémenter. Tout cela étant dit, je voudrais d'abord étudier d'autres options. Limiter vos clients est généralement un bon moyen de les contrarier. Très probablement pas la meilleure idée. :)

+0

Si vous réussissez à étrangler un client, vous devrez expliquer le cadavre. Mais ils ne seront plus ennuyés :-) –

+1

Il y a plus d'une façon d'habiller un chat ... chat. – rfeak

1

Je suppose que vous n'êtes pas en mesure d'augmenter la capacité (que ce soit via le matériel ou le logiciel), et vous avez vraiment juste besoin de limiter la charge imposée de l'extérieur sur votre serveur.

Il est préférable d'éviter ce problème au sein de votre application, sauf si vous avez des besoins très spécifiques qui ne sont pas satisfaits par les solutions existantes, qui fonctionnent au niveau du serveur HTTP. Nous avons beaucoup réfléchi à ce problème, il vaut donc la peine d'examiner les solutions existantes plutôt que de les mettre en œuvre vous-même.

Si vous utilisez Tomcat, vous pouvez configurer le nombre maximal de requêtes simultanées autorisées via les paramètres maxThreads et acceptCount. Lire l'introduction au http://tomcat.apache.org/tomcat-6.0-doc/config/http.html pour plus d'informations sur ceux-ci.

Pour les contrôles plus avancés (comme les restrictions par utilisateur), si vous effectuez un proxy via Apache, vous pouvez utiliser une variété de modules pour vous aider à gérer la situation. Quelques modules à google pour sont limitipconn, mod_bw, et mod_cband. Ceux-ci sont un peu plus difficiles à configurer et à comprendre que les contrôles de base qui sont probablement offerts par votre serveur d'applications, vous pouvez donc vouloir rester avec ceux-ci.

Questions connexes