Votre application J2EE s'exécute-t-elle lentement ? Peuvent-ils résister à la hausse du trafic ? Cet article décrit la technologie d'optimisation des performances pour développer des pages et des servlets JSP hautes performances et hautement élastiques. L’idée est de construire le plus vite possible et de s’adapter au nombre croissant d’utilisateurs et à leurs demandes. Dans cet article, je vais vous amener à apprendre des techniques pratiques et éprouvées de réglage des performances qui amélioreront considérablement les performances de vos servlets et pages jsp, améliorant ainsi les performances de J2EE. Certaines de ces technologies sont utilisées dans les phases de développement, telles que les phases de conception et de codage. Une autre partie de la technologie est liée à la configuration.
Technique 1 : mise en cache des données dans la méthode HttpServletinit()
Le serveur appelle la méthode init() du servlet après avoir créé l'instance de servlet et avant que la servlet ne traite les requêtes. Cette méthode n'est appelée qu'une seule fois dans le cycle de vie du servlet. Pour améliorer les performances, mettez en cache les données statiques dans init() ou effectuez des opérations coûteuses à effectuer lors de l'initialisation. Par exemple, une bonne pratique consiste à utiliser un pool de connexions JDBC qui implémente l'interface javax.sql.DataSource.
DataSource est obtenu à partir de l'arborescence JNDI. Il est très coûteux d'utiliser JNDI pour trouver la DataSource à chaque appel de SQL, et cela affecte sérieusement les performances de l'application. La méthode init() du Servlet peut être utilisée pour obtenir le DataSource et le mettre en cache pour une réutilisation ultérieure :
publicclassControllerServletextendsHttpServlet
{
privatejavax.sql.DataSourcetestDS=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
super.init(config);
Contextctx=null ;
essayer
{
ctx=newInitialContext();
testDS=(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
attraper (exception de dénomination)
{
ne.printStackTrace();
}
attraper (Exception)
{
e.printStackTrace();
}
}
publicjavax.sql.DataSourcegetTestDS()
{
retourtestDS ;
}
...
...
}
Technique 2 : Désactiver la fonction de chargement automatique des servlets et JSP
Vous devrez redémarrer le serveur à chaque fois que vous modifierez le Servlet/JSP. Étant donné que la fonctionnalité de chargement automatique réduit le temps de développement, cette fonctionnalité est considérée comme très utile pendant la phase de développement. Cependant, cela est très coûteux lors de la phase d'exécution ; le servlet/JSP entraîne de mauvaises performances en raison d'un chargement inutile et d'une charge accrue sur le chargeur de classe. Encore une fois, cela peut provoquer des conflits étranges dans votre application, car les classes chargées par un certain chargeur de classe ne peuvent pas coopérer avec les classes chargées par le chargeur de classe actuel. Par conséquent, afin d'obtenir de meilleures performances dans l'environnement d'exécution, désactivez la fonction de chargement automatique du servlet/JSP.
Technique 3 : Contrôler HttpSession
De nombreuses applications nécessitent une série de requêtes client afin qu'elles puissent être liées les unes aux autres. Étant donné que le protocole HTTP est sans état, les applications Web doivent être responsables du maintien d'un tel état appelé session. Afin de prendre en charge les applications qui doivent conserver leur état, la technologie Javaservlet fournit des API qui gèrent les sessions et permettent à plusieurs mécanismes d'implémenter des sessions. L'objet HttpSession agit comme une session, mais son utilisation a un coût. Chaque fois que HttpSession est utilisé et remplacé, il est lu par le servlet. Vous pouvez améliorer les performances en utilisant les techniques suivantes :
lNe créez pas de HttpSession par défaut dans la page JSP : Par défaut, la page JSP crée une HttpSession. Si vous n'utilisez pas HttpSession dans votre page JSP, afin d'économiser des performances, utilisez les instructions de page suivantes pour éviter de créer automatiquement des objets HttpSession :
< %@pagesession="false"% >
1) Ne stockez pas de graphiques d'objets volumineux dans HttpSession : si vous stockez des données dans HttpSession sous forme de graphique d'objets volumineux, le serveur d'applications devra traiter l'intégralité de l'objet HttpSession à chaque fois. Cela forcera la sérialisation Java et augmentera la surcharge de calcul. En raison de la surcharge de sérialisation, le débit du système diminuera à mesure que les objets de données stockés dans l'objet HttpSession augmenteront.
2) Libérez la HttpSession après utilisation : Lorsque la HttpSession n'est plus utilisée, utilisez la méthode HttpSession.invalidate() pour invalider la session.
3) Définissez la valeur du délai d'expiration : un moteur de servlet a une valeur de délai d'expiration par défaut. Si vous ne supprimez pas la session ou continuez à l'utiliser jusqu'à expiration, le moteur de servlet supprimera la session de la mémoire. En raison de la surcharge de mémoire et du garbage collection, plus la valeur du délai d'expiration de la session est élevée, plus son impact sur la résilience et les performances du système est important. Essayez de définir la valeur du délai d'expiration de la session aussi basse que possible.
Technique 4 : Utiliser la compression gzip
La compression consiste à supprimer les informations redondantes et à décrire vos informations dans un espace aussi petit que possible. L'utilisation de gzip (GNUzip) pour compresser des documents peut réduire efficacement le temps de téléchargement des fichiers HTML. Plus vos messages sont petits, plus ils sont envoyés rapidement. Par conséquent, si vous compressez le contenu généré par votre application Web, plus rapidement il atteint l'utilisateur et s'affiche sur l'écran de l'utilisateur. Tous les navigateurs ne prennent pas en charge la compression gzip, mais il est facile de vérifier si un navigateur la prend en charge et d'envoyer du contenu compressé gzip au navigateur. L'extrait de code ci-dessous illustre comment envoyer du contenu compressé.
publicvoiddoGet (HttpServletRequestrequest, HttpServletResponseresponse)
throwsIOException, ServletException
{
OutputStreamout=null
//Vérifie l'en-tête d'acceptation-encodage de la requête HTTP.
//Si l'en-tête inclut gzip, choisissez GZIP.
//Si l'en-tête inclut la compression, choisissez ZIP.
//Sinon, choisissez une compression.
Stringencoding=request.getHeader("Accept-Encoding");
if(encoding!=null&&encoding.indexOf("gzip")!=-1)
{
réponse.setHeader("Content-Encoding","gzip");
out=newGZIPOutputStream(response.getOutputStream());
}
elseif(encoding!=null&&encoding.indexOf("compress")!=-1)
{
réponse.setHeader("Content-Encoding","compress");
out=newZIPoutputStream(response.getOutputStream());
}
autre
{
out=response.getOutputStream()
;
...
...
}
Technique 5 : Ne pas utiliser SingleThreadModel
SingleThreadModel garantit que le servlet ne gère qu'une seule requête à la fois. Si un servlet implémente cette interface, le moteur de servlet créera une instance de servlet distincte pour chaque nouvelle requête, ce qui entraînera une surcharge système importante. Si vous devez résoudre des problèmes de sécurité des threads, veuillez utiliser d'autres méthodes au lieu de cette interface. L'utilisation de SingleThreadModel n'est plus recommandée dans Servlet2.4.
Technique 6 : utilisez le
moteur de servlet du pool de threads pour créer un thread distinct pour chaque requête, attribuez le thread à la méthode service(), puis supprimez le thread une fois la méthode service() exécutée. Par défaut, le moteur de servlet peut créer un nouveau thread pour chaque requête. Étant donné que la création et la suppression de threads coûtent cher, ce comportement par défaut réduit les performances du système. Nous pouvons utiliser un pool de threads pour améliorer les performances. En fonction du nombre attendu d'utilisateurs simultanés, configurez un pool de threads et définissez le nombre minimum et maximum de threads dans le pool de threads ainsi que les valeurs de croissance minimale et maximale. Initialement, le moteur de servlet crée un pool de threads avec un nombre de threads égal au nombre minimum de threads dans la configuration. Le moteur de servlet affecte ensuite un thread du pool à une requête au lieu de créer un nouveau thread à chaque fois. Une fois l'opération terminée, le moteur de servlet remet le thread dans le pool de threads. Grâce aux pools de threads, les performances peuvent être considérablement améliorées. Si nécessaire, davantage de threads peuvent être créés en fonction du nombre maximum de threads et du nombre de croissance.
Technique 7 : Choisissez le mécanisme d'inclusion approprié
Dans les pages JSP, il existe deux manières d'inclure des fichiers : inclure des instructions (< %@includefile="test.jsp"% >) et inclure des actions (<jsp:includepage="test.jsp " flush="true"/>). La directive include inclut le contenu d'un fichier spécifié pendant la phase de compilation, par exemple lorsqu'une page est compilée dans un servlet. Une action d'inclusion implique d'inclure le contenu du fichier pendant la phase de demande, par exemple, lorsqu'un utilisateur demande une page ; L’inclusion d’instructions est plus rapide que l’inclusion d’actions. Par conséquent, à moins que les fichiers inclus ne changent fréquemment, vous obtiendrez de meilleures performances en utilisant la directive include.
Technique 8 : Utiliser les portées appropriées dans les actions useBean
L'un des moyens les plus puissants d'utiliser les pages JSP consiste à travailler avec des composants JavaBean. Les JavaBeans peuvent être intégrés dans les pages JSP à l'aide de la balise <jsp:useBean>. La syntaxe est la suivante :
<jsp:useBeanid="name"scope="page|request|session|application"class=
"package.className"type="typeName">
</jsp:useBean>
L'attribut scope décrit la portée visible du bean. La valeur par défaut de l'attribut scope est page. Vous devez choisir la plage correcte en fonction des besoins de votre application, sinon cela affectera les performances de votre application.
Par exemple, si vous avez besoin d'un objet spécifique à une requête, mais que vous définissez la portée sur session, cet objet restera en mémoire une fois la requête terminée. Il restera en mémoire à moins que vous ne le supprimiez explicitement de la mémoire, que vous invalidiez la session ou que la session expire. Si vous ne choisissez pas le bon attribut de portée, les performances seront affectées en raison de la surcharge de mémoire et du garbage collection. Définissez donc une portée appropriée pour les objets et supprimez-les dès que vous en avez terminé avec eux.
Techniques diverses
1) Évitez la concaténation de chaînes : Les objets String étant des objets immuables, l'utilisation de l'opérateur "+" entraînera la création d'un grand nombre d'objets à temps zéro. Plus vous utilisez de "+", plus d'objets à temps zéro seront générés, ce qui affectera les performances. Lorsque vous devez concaténer des chaînes, utilisez StringBuffer au lieu de l'opération "+".
2) Évitez d'utiliser System.out.println : System.out.println traite les entrées/sorties du disque de manière synchrone, ce qui réduit considérablement le débit du système. Évitez d'utiliser System.out.println autant que possible. Bien qu'il existe de nombreux outils de débogage matures disponibles, System.out.println est parfois toujours utile à des fins de traçage ou de débogage. Vous devez configurer System.out.println pour l'ouvrir uniquement pendant les phases d'erreur et de débogage. À l'aide d'une variable finalBoolean, lorsqu'elle est configurée sur false, les contrôles d'optimisation et la sortie de trace d'exécution sont effectués pendant la phase de compilation.
3) Comparaison de ServletOutputStream et PrintWriter : en raison du flux de sortie de caractères et du codage des données en octets, l'utilisation de PrintWriter introduit une légère surcharge de performances. Par conséquent, PrintWriter doit être utilisé une fois que toutes les conversions de jeux de caractères ont été effectuées correctement. D'un autre côté, lorsque vous savez que votre servlet ne renverra que des données binaires, utilisez ServletOutputStream car le conteneur de servlet ne code pas les données binaires, vous éliminez donc la surcharge de conversion du jeu de caractères.
Résumé
Le but de cet article est de vous montrer quelques techniques d'optimisation des performances pratiques et éprouvées pour améliorer les performances des servlets et JSP, ce qui améliorera les performances globales de vos applications J2EE. L'étape suivante devrait consister à observer l'optimisation des performances d'autres technologies connexes, telles que EJB, JMS et JDBC.