¿Su aplicación J2EE funciona lentamente? ¿Podrán soportar el aumento del tráfico? Este artículo describe la tecnología de optimización del rendimiento para desarrollar servlets y páginas JSP altamente elásticas y de alto rendimiento. La idea es construir lo más rápido posible y adaptarse al creciente número de usuarios y sus solicitudes. En este artículo, lo llevaré a aprender técnicas prácticas y probadas de ajuste del rendimiento que mejorarán en gran medida el rendimiento de sus servlets y páginas jsp, mejorando así el rendimiento de J2EE. Algunas de estas tecnologías se utilizan en las fases de desarrollo, como las de diseño y codificación. Otra parte de la tecnología está relacionada con la configuración.
Técnica 1: Almacenamiento en caché de datos en el método HttpServletinit()
El servidor llama al método init() del servlet después de crear la instancia del servlet y antes de que el servlet maneje cualquier solicitud. Este método se llama sólo una vez en el ciclo de vida del servlet. Para mejorar el rendimiento, almacene en caché los datos estáticos en init() o realice operaciones costosas durante la inicialización. Por ejemplo, una práctica recomendada es utilizar un grupo de conexiones JDBC que implemente la interfaz javax.sql.DataSource.
DataSource se obtiene del árbol JNDI. Es muy costoso usar JNDI para encontrar el origen de datos cada vez que se llama a SQL y afecta seriamente el rendimiento de la aplicación. El método init() del servlet se puede utilizar para obtener el origen de datos y almacenarlo en caché para su posterior reutilización:
publicclassControllerServletextendsHttpServlet
{
privatejavax.sql.DataSourcetestDS=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
super.init(config);
Contextctx=nulo;
intentar
{
ctx=nuevoContextoInicial();
testDS=(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
captura (excepción de nombre)
{
ne.printStackTrace();
}
captura (excepción)
{
e.printStackTrace();
}
}
publicjavax.sql.DataSourcegetTestDS()
{
prueba de retornoDS;
}
...
...
}
Técnica 2: Deshabilite la función de carga automática de servlets y JSP
. Tendrá que reiniciar el servidor cada vez que modifique el Servlet/JSP. Dado que la función de carga automática reduce el tiempo de desarrollo, esta función se considera muy útil durante la fase de desarrollo. Sin embargo, es muy costoso en la fase de ejecución; servlet/JSP provoca un rendimiento deficiente debido a una carga innecesaria y una mayor carga en el cargador de clases. Nuevamente, esto puede causar que su aplicación tenga conflictos extraños porque las clases que han sido cargadas por un determinado cargador de clases no pueden cooperar con las clases cargadas por el cargador de clases actual. Por lo tanto, para obtener un mejor rendimiento en el entorno de ejecución, desactive la función de carga automática de servlet/JSP.
Técnica 3: Controlar HttpSession
Muchas aplicaciones requieren una serie de solicitudes de clientes para poder relacionarse entre sí. Dado que el protocolo HTTP no tiene estado, las aplicaciones basadas en web deben ser responsables de mantener dicho estado llamado sesión. Para admitir aplicaciones que deben mantener el estado, la tecnología Javaservlet proporciona API que administran sesiones y permiten múltiples mecanismos para implementar sesiones. El objeto HttpSession actúa como una sesión, pero su uso tiene un costo. Siempre que se utiliza y anula HttpSession, el servlet lo lee. Puede mejorar el rendimiento utilizando las siguientes técnicas:
lNo cree una sesión HttpSession predeterminada en la página JSP: de forma predeterminada, la página JSP crea una sesión Http. Si no utiliza HttpSession en su página JSP, para ahorrar sobrecarga de rendimiento, utilice las siguientes instrucciones de la página para evitar la creación automática de objetos HttpSession:
< %@pagesession="false"% >
1) No almacene gráficos de objetos grandes en HttpSession: si almacena datos en HttpSession como un gráfico de objetos grandes, el servidor de aplicaciones tendrá que procesar el objeto HttpSession completo cada vez. Esto forzará la serialización de Java y aumentará la sobrecarga computacional. Debido a la sobrecarga de la serialización, el rendimiento del sistema disminuirá a medida que aumenten los objetos de datos almacenados en el objeto HttpSession.
2) Libere HttpSession después de su uso: cuando HttpSession ya no esté en uso, use el método HttpSession.invalidate() para invalidar la sesión.
3) Establezca el valor de tiempo de espera: un motor de servlet tiene un valor de tiempo de espera predeterminado. Si no elimina la sesión o continúa usándola hasta que se agote el tiempo de espera, el motor de servlet eliminará la sesión de la memoria. Debido a la sobrecarga de memoria y recolección de basura, cuanto mayor sea el valor del tiempo de espera de la sesión, mayor será su impacto en la resistencia y el rendimiento del sistema. Intente establecer el valor del tiempo de espera de la sesión lo más bajo posible.
Técnica 4: Utilice la compresión gzip
La compresión es la práctica de eliminar información redundante y describir su información en el espacio más pequeño posible. El uso de gzip (GNUzip) para comprimir documentos puede reducir eficazmente el tiempo de descarga de archivos HTML. Cuanto más pequeños sean tus mensajes, más rápido se enviarán. Por lo tanto, si comprime el contenido generado por su aplicación web, más rápido llega al usuario y se muestra en su pantalla. No todos los navegadores admiten la compresión gzip, pero es fácil comprobar si un navegador la admite y enviar contenido comprimido con gzip al navegador. El siguiente fragmento de código ilustra cómo enviar contenido comprimido.
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
lanzaIOException,ServletException
{
OutputStreamout=null
//Verifique el encabezado de codificación de aceptación de la solicitud HTTP.
//Si el encabezado incluye gzip, elija GZIP.
//Si el encabezado incluye comprimir, elija ZIP.
//De lo contrario, elija una compresión.
Stringencoding=request.getHeader("Accept-Encoding");
if(encoding!=null&&encoding.indexOf("gzip")!=-1)
{
respuesta.setHeader("Codificación de contenido","gzip");
salida=newGZIPOutputStream(response.getOutputStream());
}
elseif(codificación!=null&&codificación.indexOf("comprimir")!=-1)
{
respuesta.setHeader("Codificación de contenido","comprimir");
salida=newZIPOutputStream(response.getOutputStream());
}
demás
{
salida=respuesta.getOutputStream()
;
...
...
}
Técnica 5: No utilice SingleThreadModel
SingleThreadModel garantiza que el servlet sólo maneja una solicitud a la vez. Si un servlet implementa esta interfaz, el motor de servlet creará una instancia de servlet separada para cada nueva solicitud, lo que provocará una gran sobrecarga del sistema. Si necesita resolver problemas de seguridad de subprocesos, utilice otros métodos en lugar de esta interfaz. Ya no se recomienda el uso de SingleThreadModel en Servlet2.4.
Técnica 6: utilice el
motor de servlet del grupo de subprocesos para crear un subproceso separado para cada solicitud, asigne el subproceso al método service() y luego elimine el subproceso después de ejecutar el método service(). De forma predeterminada, el motor de servlet puede crear un nuevo hilo para cada solicitud. Dado que crear y eliminar subprocesos es costoso, este comportamiento predeterminado reduce el rendimiento del sistema. Podemos utilizar el grupo de subprocesos para mejorar el rendimiento. De acuerdo con la cantidad esperada de usuarios simultáneos, configure un grupo de subprocesos y establezca la cantidad mínima y máxima de subprocesos en el grupo de subprocesos, así como los valores de crecimiento mínimo y máximo. Inicialmente, el motor de servlet crea un grupo de subprocesos con una cantidad de subprocesos igual a la cantidad mínima de subprocesos en la configuración. Luego, el motor de servlet asigna un subproceso del grupo a una solicitud en lugar de crear un nuevo subproceso cada vez. Después de completar la operación, el motor de servlet vuelve a colocar el subproceso en el grupo de subprocesos. Al utilizar grupos de subprocesos, el rendimiento se puede mejorar significativamente. Si es necesario, se pueden crear más subprocesos según la cantidad máxima de subprocesos y la cantidad de crecimiento.
Técnica 7: elegir el mecanismo de inclusión correcto
En las páginas JSP, hay dos formas de incluir archivos: incluir instrucciones (< %@includefile="test.jsp"% >) e incluir acciones (<jsp:includepage="test.jsp " enjuague="verdadero"/>). La directiva de inclusión incluye el contenido de un archivo específico durante la fase de compilación, por ejemplo, cuando una página se compila en un servlet. Una acción de inclusión implica incluir contenido del archivo durante la fase de solicitud, por ejemplo, cuando un usuario solicita una página. Incluir instrucciones es más rápido que incluir acciones. Por lo tanto, a menos que los archivos incluidos cambien con frecuencia, obtendrá un mejor rendimiento utilizando la directiva include.
Técnica 8: Usar ámbitos apropiados en acciones useBean
Una de las formas más poderosas de usar páginas JSP es trabajar con componentes JavaBean. Los JavaBeans se pueden incrustar en páginas JSP utilizando la etiqueta <jsp:useBean>. La sintaxis es la siguiente:
<jsp:useBeanid="name"scope="page|request|session|application"class=
"paquete.nombredeclase"tipo="nombretipo">
</jsp:useBean>
El atributo de alcance describe el alcance visible del bean. El valor predeterminado del atributo de alcance es página. Debe elegir el rango correcto según las necesidades de su aplicación; de lo contrario, afectará el rendimiento de su aplicación.
Por ejemplo, si necesita un objeto específico para alguna solicitud, pero establece el alcance en sesión, ese objeto permanecerá en la memoria después de que finalice la solicitud. Permanecerá en la memoria a menos que lo elimine explícitamente de la memoria, invalide la sesión o se agote el tiempo de espera de la sesión. Si no elige el atributo de alcance correcto, el rendimiento se verá afectado debido a la sobrecarga de memoria y recolección de basura. Así que establezca un alcance adecuado para los objetos y elimínelos tan pronto como haya terminado con ellos.
Técnicas diversas
1) Evite la concatenación de cadenas: dado que los objetos String son objetos inmutables, el uso del operador "+" dará como resultado la creación de una gran cantidad de objetos de tiempo cero. Cuanto más "+" utilice, más objetos de tiempo cero se generarán, lo que afectará el rendimiento. Cuando necesite concatenar cadenas, utilice StringBuffer en lugar de la operación "+".
2) Evite el uso de System.out.println: System.out.println procesa la entrada/salida del disco de forma sincrónica, lo que reduce en gran medida el rendimiento del sistema. Evite utilizar System.out.println siempre que sea posible. Aunque hay muchas herramientas de depuración maduras disponibles, a veces System.out.println sigue siendo útil para fines de seguimiento o depuración. Debe configurar System.out.println para que solo lo abra durante las fases de error y depuración. Al utilizar una variable finalBoolean, cuando se configura en falso, las comprobaciones de optimización y la salida del seguimiento de ejecución se completan durante la fase de compilación.
3) Comparación de ServletOutputStream y PrintWriter: debido al flujo de salida de caracteres y la codificación de datos en bytes, el uso de PrintWriter introduce una pequeña sobrecarga de rendimiento. Por lo tanto, se debe utilizar PrintWriter después de que todas las conversiones de juegos de caracteres se hayan realizado correctamente. Por otro lado, cuando sepa que su servlet solo devolverá datos binarios, use ServletOutputStream porque el contenedor de servlets no codifica datos binarios, por lo que elimina la sobrecarga de conversión del juego de caracteres.
Resumen
El propósito de este artículo es mostrarle algunas técnicas prácticas y comprobadas de optimización del rendimiento para mejorar el rendimiento de servlets y JSP, que mejorarán el rendimiento general de sus aplicaciones J2EE. El siguiente paso debería ser observar el ajuste del rendimiento de otras tecnologías relacionadas, como EJB, JMS y JDBC.