คุณมักจะได้รับการร้องเรียนจากลูกค้าเกี่ยวกับความเร็วในการตอบสนองที่ช้าของเพจ JSP หรือไม่? คุณเคยคิดบ้างไหมว่าแอปพลิเคชันเว็บของคุณสามารถทนต่อจำนวนการเข้าชมที่เพิ่มขึ้นเมื่อจำนวนการเข้าชมของลูกค้าเพิ่มขึ้นอย่างมากได้อย่างไร บทความนี้จะอธิบายวิธีการที่เป็นประโยชน์อย่างยิ่งในการปรับ JSP และเซิร์ฟเล็ต ซึ่งสามารถทำให้เซิร์ฟเล็ตและเพจ JSP ของคุณตอบสนองและปรับขนาดได้มากขึ้น นอกจากนี้ เมื่อจำนวนผู้ใช้เพิ่มขึ้น โหลดของระบบจะแสดงแนวโน้มขาขึ้นอย่างราบรื่น ในบทความนี้ ฉันจะใช้ตัวอย่างที่เป็นประโยชน์และวิธีการกำหนดค่าเพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชันของคุณโดยไม่คาดคิด เทคนิคการปรับแต่งบางส่วนเหล่านี้ถูกนำมาใช้ในงานเขียนโปรแกรมของคุณ เทคโนโลยีอื่นๆ เกี่ยวข้องกับการกำหนดค่าของแอปพลิเคชันเซิร์ฟเวอร์ ในบทความนี้ เราจะอธิบายรายละเอียดวิธีปรับปรุงประสิทธิภาพโดยรวมของแอปพลิเคชันของคุณโดยการปรับแต่งเซิร์ฟเล็ตและเพจ JSP ก่อนที่จะอ่านบทความนี้ จะถือว่าคุณมีความรู้พื้นฐานเกี่ยวกับเซิร์ฟเล็ตและ JSP
วิธีที่ 1: ข้อมูลแคชในเมธอด init() ของเซิร์ฟเล็ต
หลังจากที่แอปพลิเคชันเซิร์ฟเวอร์เตรียมใช้งานอินสแตนซ์เซิร์ฟเล็ตและก่อนที่จะให้บริการคำขอของไคลเอ็นต์ จะเรียกเมธอด init() ของเซิร์ฟเล็ต ในวงจรชีวิตของเซิร์ฟเล็ต เมธอด init() จะถูกเรียกเพียงครั้งเดียวเท่านั้น ด้วยการแคชข้อมูลคงที่บางส่วนในเมธอด init() หรือดำเนินการบางอย่างที่ใช้เวลานานซึ่งต้องทำเพียงครั้งเดียว จะทำให้ประสิทธิภาพของระบบดีขึ้นอย่างมาก
ตัวอย่างเช่น การสร้างพูลการเชื่อมต่อ JDBC ในเมธอด init() เป็นตัวอย่างที่ดีที่สุด สมมติว่าเราใช้อินเทอร์เฟซ DataSource ของ jdbc2.0 เพื่อรับการเชื่อมต่อฐานข้อมูล ภายใต้สถานการณ์ปกติ เราจำเป็นต้องได้รับข้อมูลเฉพาะผ่าน JNDI เราสามารถจินตนาการได้ว่าในแอปพลิเคชันเฉพาะ หากมีการดำเนินการแบบสอบถาม JNDI สำหรับทุกคำขอ SQL ประสิทธิภาพของระบบจะลดลงอย่างรวดเร็ว วิธีแก้ไขคือโค้ดต่อไปนี้ ซึ่งจะแคชแหล่งข้อมูลเพื่อให้ยังคงสามารถใช้งานได้ในระหว่างการเรียก SQL ครั้งถัดไป:
public class ControllerServlet ขยาย HttpServlet
-
javax.sql.DataSource ส่วนตัว testDS = null;
โมฆะสาธารณะ init (การกำหนดค่า ServletConfig) พ่น ServletException
-
super.init(กำหนดค่า);
บริบท ctx = null;
พยายาม
-
ctx = InitialContext ใหม่ ();
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
-
จับ (การตั้งชื่อข้อยกเว้น NE)
-
ne.printStackTrace();
-
จับ (ยกเว้น e)
-
e.printStackTrace();
-
}
สาธารณะ javax.sql.DataSource getTestDS()
-
กลับ testDS;
-
-
-
}
วิธีที่ 2: ปิดใช้งานการโหลดเซิร์ฟเล็ตและ JSP อัตโนมัติ (โหลดซ้ำอัตโนมัติ)
Servlet/JSP มีเทคโนโลยีที่ใช้งานได้จริง กล่าวคือ เทคโนโลยีการโหลดซ้ำอัตโนมัติ ซึ่งช่วยให้นักพัฒนามีสภาพแวดล้อมการพัฒนาที่ดี เมื่อคุณเปลี่ยนเซิร์ฟเล็ตและเพจ JSP โดยไม่ต้องรีสตาร์ทแอปพลิเคชัน เซิร์ฟเวอร์ อย่างไรก็ตาม เทคโนโลยีนี้เป็นการสูญเสียทรัพยากรระบบอย่างมากในระหว่างขั้นตอนการรันผลิตภัณฑ์ เนื่องจากจะนำภาระมหาศาลมาสู่คลาสโหลดเดอร์ของเอ็นจิ้น JSP ดังนั้นการปิดฟังก์ชันโหลดซ้ำอัตโนมัติจึงช่วยปรับปรุงประสิทธิภาพของระบบได้มาก
วิธีที่ 3: อย่าใช้ HttpSession ในทางที่ผิด
ในหลาย ๆ แอปพลิเคชัน โปรแกรมของเราจำเป็นต้องรักษาสถานะของไคลเอนต์เพื่อให้เพจสามารถสื่อสารระหว่างกันได้ แต่น่าเสียดาย เนื่องจาก HTTP ไม่มีสถานะโดยธรรมชาติ จึงไม่สามารถบันทึกสถานะของไคลเอ็นต์ได้ ดังนั้นแอปพลิเคชันเซิร์ฟเวอร์ทั่วไปจึงมีเซสชันเพื่อบันทึกสถานะของไคลเอ็นต์ ในแอปพลิเคชันเซิร์ฟเวอร์ JSP ฟังก์ชันเซสชันจะถูกนำไปใช้ผ่านออบเจ็กต์ HttpSession แต่ถึงแม้จะสะดวก แต่ก็นำภาระมาสู่ระบบเช่นกัน เนื่องจากทุกครั้งที่คุณได้รับหรืออัปเดตเซสชัน ผู้ควบคุมระบบจะต้องดำเนินการซีเรียลไลซ์เซสชันที่ใช้เวลานาน คุณสามารถปรับปรุงประสิทธิภาพของระบบได้โดยการจัดการ HttpSession ด้วยวิธีต่อไปนี้:
· หากไม่จำเป็น คุณควรปิดการตั้งค่าเริ่มต้นสำหรับ HttpSession ในเพจ JSP: หากคุณไม่ได้ระบุอย่างชัดเจน แต่ละเพจ JSP จะใช้ค่าเริ่มต้นเป็น Create an HttpSession . หากคุณไม่จำเป็นต้องใช้เซสชันใน JSP ของคุณ คุณสามารถปิดการใช้งานได้โดยใช้ตัวบ่งชี้เพจ JSP ต่อไปนี้:
<%@ page session="false"%>
· อย่าเก็บออบเจ็กต์ข้อมูลขนาดใหญ่ใน HttpSession: หากคุณหากข้อมูลขนาดใหญ่ อ็อบเจ็กต์ถูกจัดเก็บไว้ใน HttpSession แอปพลิเคชันเซิร์ฟเวอร์จะทำซีเรียลไลซ์มันทุกครั้งที่อ่านหรือเขียน ซึ่งจะเป็นการเพิ่มภาระพิเศษให้กับระบบ ยิ่งวัตถุข้อมูลที่คุณจัดเก็บไว้ใน HttpSession มีขนาดใหญ่เท่าใด ประสิทธิภาพของระบบจะลดลงเร็วขึ้นเท่านั้น
· เมื่อคุณไม่ต้องการ HttpSession อีกต่อไป ให้ปล่อยโดยเร็วที่สุด: เมื่อคุณไม่ต้องการเซสชันอีกต่อไป คุณสามารถปล่อยได้โดยการเรียกเมธอด HttpSession.invalidate()
· พยายามตั้งค่าการหมดเวลาเซสชันให้สั้นที่สุด: ในแอปพลิเคชันเซิร์ฟเวอร์ JSP มีการหมดเวลาเซสชันเริ่มต้น เมื่อลูกค้าไม่ดำเนินการใดๆ หลังจากเวลานี้ ระบบจะปล่อยเซสชันที่เกี่ยวข้องออกจากหน่วยความจำโดยอัตโนมัติ ยิ่งตั้งค่าการหมดเวลาไว้มากเท่าใด ประสิทธิภาพของระบบก็จะยิ่งต่ำลง ดังนั้นวิธีที่ดีที่สุดคือพยายามรักษาค่าให้ต่ำที่สุดเท่าที่จะเป็นไปได้
วิธีที่ 4: การบีบอัดเอาต์พุตเพจ
เป็นวิธีที่ดีในการแก้ปัญหาความซ้ำซ้อนของข้อมูล โดยเฉพาะอย่างยิ่งในปัจจุบัน เมื่อแบนด์วิดท์เครือข่ายยังไม่ได้รับการพัฒนาเพียงพอ เบราว์เซอร์บางตัวรองรับ gzip (GNU zip) เพื่อบีบอัดไฟล์ HTML วิธีนี้สามารถลดเวลาในการดาวน์โหลดไฟล์ HTML ได้อย่างมาก ดังนั้น หากคุณบีบอัดเพจ HTML ที่สร้างโดยเซิร์ฟเล็ตหรือเพจ JSP ผู้ใช้จะรู้สึกว่าความเร็วในการเรียกดูเพจจะเร็วมาก ขออภัย ไม่ใช่ทุกเบราว์เซอร์ที่รองรับการบีบอัด gzip แต่คุณสามารถตรวจสอบในโปรแกรมของคุณได้ว่าเบราว์เซอร์ของลูกค้ารองรับหรือไม่ ต่อไปนี้เป็นตัวอย่างโค้ดสำหรับการใช้งานวิธีนี้:
โมฆะสาธารณะ doGet (คำขอ HttpServletRequest, การตอบสนอง HttpServletResponse)
พ่น IOException, ServletException
-
OutputStream ออก = null
การเข้ารหัสสตริง = request.getHeader("ยอมรับการเข้ารหัส");
ถ้า (การเข้ารหัส != null && encoding.indexOf("gzip") != -1)
-
request.setHeader("การเข้ารหัสเนื้อหา" , "gzip");
ออก = GZIPOutputStream ใหม่ (request.getOutputStream());
-
อย่างอื่นถ้า (การเข้ารหัส != null && encoding.indexOf("compress") != -1)
-
request.setHeader("การเข้ารหัสเนื้อหา" , "บีบอัด");
ออก = ZIPOutputStream ใหม่ (request.getOutputStream());
-
อื่น
-
ออก = request.getOutputStream();
-
-
-
}
วิธีที่ 5: ใช้เธรดพูล
แอปพลิเคชันเซิร์ฟเวอร์สร้างเธรดสำหรับการประมวลผลคำขอไคลเอนต์ที่แตกต่างกันตามค่าเริ่มต้น และกำหนดเมธอด service() ให้กับเธรดเหล่านั้น เมื่อการเรียกใช้เมธอด service() เสร็จสิ้น เธรดที่เกี่ยวข้องก็จะยกเลิกไปด้วย . เนื่องจากการสร้างและการทำลายเธรดต้องใช้ทรัพยากรระบบบางอย่าง โหมดเริ่มต้นนี้จะลดประสิทธิภาพของระบบ แต่โชคดีที่เราสามารถเปลี่ยนสถานการณ์นี้ได้โดยการสร้างกลุ่มเธรด นอกจากนี้ เรายังจำเป็นต้องตั้งค่าจำนวนเธรดขั้นต่ำและจำนวนเธรดสูงสุดสำหรับกลุ่มเธรดนี้ เมื่อแอปพลิเคชันเซิร์ฟเวอร์เริ่มต้น จะสร้างเธรดพูลด้วยจำนวนเท่ากับจำนวนเธรดขั้นต่ำ เมื่อลูกค้ามีคำขอ เธรดจะถูกนำออกจากพูลเพื่อการประมวลผล เมื่อการประมวลผลเสร็จสิ้น เธรดจะถูก นำกลับลงสระตรงกลาง หากมีเธรดในพูลไม่เพียงพอ ระบบจะเพิ่มจำนวนเธรดในพูลโดยอัตโนมัติ แต่จำนวนทั้งหมดต้องไม่เกินจำนวนเธรดสูงสุด ด้วยการใช้เธรดพูล เมื่อคำขอของไคลเอ็นต์เพิ่มขึ้นอย่างรวดเร็ว โหลดของระบบจะแสดงเส้นโค้งขึ้นอย่างราบรื่น ซึ่งจะช่วยปรับปรุงความสามารถในการปรับขนาดของระบบ
วิธีที่ 6: เลือกกลไกการรวมเพจที่ถูกต้อง
มีสองวิธีใน JSP ที่สามารถใช้เพื่อรวมเพจอื่น: 1. ใช้ตัวบ่งชี้การรวม (<%@ includee file="test.jsp" %>) 2. ใช้ตัวบ่งชี้ jsp (<jsp:includee page="test.jsp" flush="true"/>) ในทางปฏิบัติฉันพบว่าหากคุณใช้วิธีแรก ประสิทธิภาพของระบบอาจสูงขึ้นได้
วิธีที่ 7: กำหนดวงจรชีวิตของ javabeans อย่างถูกต้อง
หนึ่งในแง่มุมที่ทรงพลังของ JSP คือการรองรับ javabeans โดยการใช้แท็ก <jsp:useBean> ในเพจ JSP คุณสามารถแทรก javabeans ลงในเพจ JSP ได้โดยตรง การใช้งานมีดังนี้:
<jsp:useBean id="name" scope="page|request|session|application" class=
"package.className" type="typeName">
</jsp:useBean>
แอตทริบิวต์ขอบเขตจะชี้ให้เห็นวงจรชีวิตของ bean นี้ วงจรชีวิตเริ่มต้นคือเพจ หากคุณเลือกวงจรชีวิตของ bean ไม่ถูกต้อง จะส่งผลต่อประสิทธิภาพของระบบ
ตัวอย่างเช่น หากคุณต้องการใช้ bean บางตัวในคำขอเดียว แต่คุณตั้งค่าวงจรชีวิตของ bean ให้เป็นเซสชัน เมื่อคำขอสิ้นสุดลง bean จะยังคงอยู่ในหน่วยความจำ เว้นแต่เซสชันหมดเวลาหรือผู้ใช้จะปิดเบราว์เซอร์ ซึ่งจะใช้หน่วยความจำจำนวนหนึ่งและเพิ่มเวิร์กโหลดของตัวรวบรวมขยะ JVM โดยไม่จำเป็น ดังนั้น การตั้งค่าวงจรชีวิตที่ถูกต้องสำหรับ bean และการทำความสะอาดโดยเร็วที่สุดหลังจากภารกิจสิ้นสุดลง จะช่วยปรับปรุงประสิทธิภาพของระบบ
วิธีการที่มีประโยชน์อื่นๆ
: พยายามอย่าใช้ตัวดำเนินการ "+" ในการดำเนินการต่อสตริง: ในการเขียนโปรแกรม Java เรามักจะใช้ตัวดำเนินการ "+" เพื่อเชื่อมต่อหลายสตริง แต่คุณอาจไม่เคยคิดเลยว่ามันจะส่งผลต่อระบบจริงๆ ประสิทธิภาพใช่ไหม? เนื่องจากสตริงเป็นค่าคงที่ JVM จะสร้างอ็อบเจ็กต์ชั่วคราวบางส่วน ยิ่งคุณใช้ "+" มากเท่าไร ออบเจ็กต์ชั่วคราวก็จะถูกสร้างขึ้นมากขึ้นเท่านั้น ซึ่งจะมีผลกระทบต่อประสิทธิภาพของระบบด้วย วิธีแก้ไขคือใช้วัตถุ StringBuffer แทนตัวดำเนินการ "+"
· หลีกเลี่ยงการใช้เมธอด System.out.println(): เนื่องจาก System.out.println() เป็นการเรียกแบบซิงโครนัส นั่นคือ เมื่อทำการเรียก การดำเนินการ I/O ของดิสก์ต้องรอจนเสร็จสิ้น ดังนั้นเราควรพยายาม หลีกเลี่ยงการใช้มันโทร แต่เป็นเครื่องมือที่ขาดไม่ได้และสะดวกสบายเมื่อเราทำการดีบักโปรแกรม เพื่อที่จะแก้ไขข้อขัดแย้งนี้ ฉันขอแนะนำให้คุณใช้เครื่องมือ Log4j ( http://Jakarta.apache.org ) ซึ่งสามารถอำนวยความสะดวกในการดีบักโดยไม่ต้องใช้วิธีเช่น System.out .println() จะถูกสร้างขึ้น
· การแลกเปลี่ยนระหว่าง ServletOutputStream และ PrintWriter: การใช้ PrintWriter อาจมีค่าใช้จ่ายเล็กน้อย เนื่องจากจะแปลงเอาต์พุตดิบทั้งหมดเป็นสตรีมอักขระสำหรับเอาต์พุต ดังนั้นหากใช้เป็นเอาต์พุตเพจ ระบบจะต้องรับกระบวนการแปลง ไม่มีปัญหาหากคุณใช้ ServletOutputStream เป็นเอาต์พุตเพจ แต่เป็นเอาต์พุตในรูปแบบไบนารี ดังนั้นจึงต้องชั่งน้ำหนักข้อดีข้อเสียของทั้งสองอย่างในการใช้งานจริง
สรุป
วัตถุประสงค์ของบทความนี้คือเพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชันของคุณอย่างมากผ่านเทคนิคการปรับแต่งบางอย่างสำหรับเซิร์ฟเล็ตและ JSP และปรับปรุงประสิทธิภาพของแอปพลิเคชัน J2EE ทั้งหมด ด้วยเทคนิคการปรับแต่งเหล่านี้ คุณจะพบว่าไม่ใช่แพลตฟอร์มทางเทคนิคบางอย่าง (เช่น ข้อพิพาทระหว่าง J2EE และ .NET) ที่กำหนดประสิทธิภาพของแอปพลิเคชันของคุณ สิ่งสำคัญคือคุณต้องมีความเข้าใจอย่างลึกซึ้งเกี่ยวกับแพลตฟอร์มนี้ เมื่อนั้นคุณจะสามารถเพิ่มประสิทธิภาพแอปพลิเคชันของคุณโดยพื้นฐานได้!