هل تتلقى غالبًا شكاوى من العملاء بشأن بطء سرعة الاستجابة لصفحات JSP؟ هل فكرت يومًا كيف يمكن لتطبيق الويب الخاص بك أن يتحمل العدد المتزايد من الزيارات عندما يزيد عدد زيارات العملاء بشكل كبير؟ توضح هذه المقالة بعض الطرق العملية جدًا لضبط JSP وservlets، والتي يمكن أن تجعل صفحات servlet وJSP الخاصة بك أكثر استجابة وأكثر قابلية للتوسع. علاوة على ذلك، مع زيادة عدد المستخدمين، سيظهر حمل النظام اتجاهًا تصاعديًا سلسًا. في هذه المقالة، سأستخدم بعض الأمثلة العملية وطرق التكوين لتحسين أداء تطبيقك بشكل غير متوقع. يتم تنفيذ بعض تقنيات الضبط هذه في أعمال البرمجة الخاصة بك. ترتبط التقنيات الأخرى بتكوين خادم التطبيق. في هذه المقالة، سنصف بالتفصيل كيفية تحسين الأداء العام لتطبيقك عن طريق ضبط servlets وصفحات JSP. قبل قراءة هذه المقالة، من المفترض أن لديك المعرفة الأساسية بـ servlets وJSP.
الطريقة الأولى: تخزين البيانات مؤقتًا في طريقة init() الخاصة بـ servlet
بعد أن يقوم خادم التطبيق بتهيئة مثيل servlet وقبل تقديم طلبات العميل، فإنه يستدعي طريقة init() الخاصة بـ servlet. في دورة حياة servlet، سيتم استدعاء الأسلوب init() مرة واحدة فقط. من خلال تخزين بعض البيانات الثابتة مؤقتًا في طريقة init() أو إكمال بعض العمليات التي تستغرق وقتًا طويلاً والتي تحتاج إلى تنفيذها مرة واحدة فقط، يمكن تحسين أداء النظام بشكل كبير.
على سبيل المثال، يعد إنشاء تجمع اتصال JDBC في طريقة init () أفضل مثال. لنفترض أننا نستخدم واجهة DataSource لـ jdbc2.0 للحصول على اتصال بقاعدة البيانات، في الظروف العادية، نحتاج إلى الحصول على بيانات محددة من خلال مصدر JNDI. يمكننا أن نتخيل أنه في تطبيق معين، إذا تم تنفيذ استعلام JNDI لكل طلب SQL، فسوف ينخفض أداء النظام بشكل حاد. الحل هو الكود التالي، الذي يقوم بتخزين DataSource مؤقتًا بحيث لا يزال من الممكن استخدامه أثناء استدعاء SQL التالي:
الطبقة العامة ControllerServlet يمتد HttpServlet
{
public javax.sql.DataSource testDS = null;
init الفراغ العام (تكوين ServletConfig) يلقي ServletException
{
super.init(config);
السياق ctx = null;
يحاول
{
ctx = new originalContext();
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
قبض على (NamingException ني)
{
printStackTrace();
}
قبض (استثناء ه)
{
printStackTrace();
}
}
javax.sql.DataSource getTestDS() العامة
{
اختبار العودة؛
}
...
...
}
الطريقة الثانية: تعطيل إعادة التحميل التلقائي لـ servlet وJSP (إعادة التحميل التلقائي)
يوفر Servlet/JSP تقنية عملية، وهي تقنية إعادة التحميل التلقائي، والتي توفر للمطورين بيئة تطوير جيدة عند تغيير صفحة servlet وJSP دون الحاجة إلى إعادة تشغيل التطبيق الخادم. ومع ذلك، فإن هذه التقنية تمثل خسارة كبيرة لموارد النظام أثناء مرحلة تشغيل المنتج، لأنها ستجلب عبئًا كبيرًا على محمل الفئة لمحرك JSP. لذلك، يعد إيقاف تشغيل وظيفة إعادة التحميل التلقائي بمثابة مساعدة كبيرة لتحسين أداء النظام.
الطريقة الثالثة: لا تسيء استخدام HttpSession
في العديد من التطبيقات، يحتاج برنامجنا إلى الحفاظ على حالة العميل حتى تتمكن الصفحات من التواصل مع بعضها البعض. لكن لسوء الحظ، نظرًا لأن HTTP عديم الحالة بطبيعته، فلا يمكنه حفظ حالة العميل. ولذلك، توفر خوادم التطبيقات العامة جلسات لحفظ حالة العميل. في خادم تطبيقات JSP، يتم تنفيذ وظيفة الجلسة من خلال كائن HttpSession، ولكن على الرغم من أنها مريحة، إلا أنها تجلب أيضًا الكثير من العبء على النظام. لأنه في كل مرة تحصل فيها على جلسة أو تقوم بتحديثها، يتعين على مشغل النظام إجراء عمليات تسلسل تستغرق وقتًا طويلاً عليها. يمكنك تحسين أداء النظام عن طريق التعامل مع جلسة HttpSession بالطرق التالية:
· إذا لم يكن ذلك ضروريًا، فيجب عليك إيقاف تشغيل الإعدادات الافتراضية لـ HttpSession في صفحة JSP: إذا لم تحددها بشكل صريح، فستكون كل صفحة JSP افتراضية على إنشاء HttpSession . إذا لم تكن بحاجة إلى استخدام الجلسة في JSP الخاص بك، فيمكنك تعطيلها من خلال مؤشر صفحة JSP التالي:
<%@ page session="false"%>
· لا تقم بتخزين كائنات البيانات الكبيرة في جلسة HttpSession: إذا كنت تحتوي على بيانات كبيرة إذا تم تخزين الكائن في HttpSession، فسيقوم خادم التطبيق بإجراء تسلسل له في كل مرة تتم قراءته أو كتابته، مما يضيف عبئًا إضافيًا على النظام. كلما زاد حجم كائن البيانات الذي تقوم بتخزينه في HttpSession، انخفض أداء النظام بشكل أسرع.
· عندما لم تعد بحاجة إلى جلسة HttpSession، قم بتحريرها في أقرب وقت ممكن: عندما لم تعد بحاجة إلى الجلسة، يمكنك تحريرها عن طريق استدعاء الأسلوب HttpSession.invalidate().
· حاول تعيين مهلة الجلسة قصيرة قدر الإمكان: في خادم تطبيقات JSP، هناك مهلة افتراضية للجلسة. عندما لا يقوم العميل بإجراء أي عمليات بعد هذا الوقت، سيقوم النظام تلقائيًا بتحرير الجلسة ذات الصلة من الذاكرة. كلما تم ضبط المهلة بشكل أكبر، انخفض أداء النظام، لذا فإن أفضل طريقة هي محاولة إبقاء قيمتها منخفضة قدر الإمكان.
الطريقة الرابعة: يعد ضغط إخراج الصفحة
طريقة جيدة لحل مشكلة تكرار البيانات، خاصة اليوم عندما لا يتم تطوير النطاق الترددي للشبكة بشكل كافٍ. تدعم بعض المتصفحات gzip (GNU zip) لضغط ملفات HTML. يمكن لهذه الطريقة تقليل وقت تنزيل ملفات HTML بشكل كبير. لذلك، إذا قمت بضغط صفحة HTML التي تم إنشاؤها بواسطة صفحة servlet أو JSP، فسيشعر المستخدم أن سرعة تصفح الصفحة ستكون سريعة جدًا. لسوء الحظ، لا تدعم جميع المتصفحات ضغط gzip، ولكن يمكنك التحقق في برنامجك مما إذا كان متصفح العميل يدعمه. فيما يلي مقتطف التعليمات البرمجية لتنفيذ هذه الطريقة:
public void doGet(HttpServletRequest request, HttpServletResponse Response)
يلقي IOException، ServletException
{
OutputStream out = null
ترميز السلسلة = request.getHeader("Accept-Encoding");
إذا (ترميز != null && encoding.indexOf("gzip") != -1)
{
request.setHeader("ترميز المحتوى" , "gzip");
out = new GZIPOutputStream(request.getOutputStream());
}
وإلا إذا (ترميز != null && encoding.indexOf("compress")!= -1)
{
request.setHeader("ترميز المحتوى" , "ضغط");
out = new ZIPOutputStream(request.getOutputStream());
}
آخر
{
out = request.getOutputStream();
}
...
...
}
الطريقة الخامسة: استخدم تجمع مؤشرات الترابط.
يقوم خادم التطبيق بإنشاء مؤشر ترابط لمعالجة كل طلب عميل مختلف بشكل افتراضي، ثم يقوم بتعيين طريقة الخدمة () لهم، ثم يتم إلغاء مؤشر الترابط المقابل أيضًا . نظرًا لأن إنشاء سلاسل الرسائل وتدميرها يستهلك موارد نظام معينة، فإن هذا الوضع الافتراضي يقلل من أداء النظام. لكن لحسن الحظ يمكننا تغيير هذا الوضع عن طريق إنشاء تجمع مؤشرات الترابط. بالإضافة إلى ذلك، نحتاج أيضًا إلى تعيين الحد الأدنى لعدد سلاسل الرسائل والحد الأقصى لعدد سلاسل الرسائل لتجمع سلاسل الرسائل هذا. عندما يبدأ خادم التطبيق، سيقوم بإنشاء تجمع مؤشرات ترابط برقم يساوي الحد الأدنى لعدد سلاسل الرسائل. عندما يكون لدى العميل طلب، يتم إخراج مؤشر الترابط من التجمع للمعالجة ضعه مرة أخرى في حمام السباحة. إذا لم تكن هناك سلاسل رسائل كافية في التجمع، فسيقوم النظام تلقائيًا بزيادة عدد سلاسل الرسائل في التجمع، ولكن لا يمكن أن يتجاوز العدد الإجمالي الحد الأقصى لعدد سلاسل الرسائل. باستخدام تجمع مؤشرات الترابط، عندما تزيد طلبات العميل بشكل حاد، سيُظهر حمل النظام منحنى تصاعديًا سلسًا، وبالتالي تحسين قابلية التوسع للنظام.
الطريقة السادسة: اختيار آلية تضمين الصفحة الصحيحة
هناك طريقتان في JSP يمكن استخدامهما لتضمين صفحة أخرى: 1. استخدم مؤشر التضمين (<%@ includee file="test.jsp" %>). 2. استخدم مؤشر jsp (<jsp:includee page="test.jsp" Flush="true"/>). من الناحية العملية، وجدت أنه إذا استخدمت الطريقة الأولى، يمكن أن يكون أداء النظام أعلى.
الطريقة السابعة: تحديد دورة حياة Javabeans بشكل صحيح
أحد الجوانب القوية لـ JSP هو دعمه لـ javabeans. باستخدام العلامة <jsp:useBean> في صفحة JSP، يمكن إدراج برامج javabeans مباشرةً في صفحة JSP. استخدامه كما يلي:
<jsp:useBean id="name"scope="page|request|session|application" class=
"package.className" type="typeName">
</jsp:useBean>
تشير سمة النطاق إلى دورة حياة هذه الحبة. دورة الحياة الافتراضية هي الصفحة. إذا لم تقم باختيار دورة حياة الفول بشكل صحيح، فسوف يؤثر ذلك على أداء النظام.
على سبيل المثال، إذا كنت تريد فقط استخدام حبة معينة في طلب واحد، ولكنك قمت بتعيين دورة حياة الحبة على الجلسة، فعند انتهاء الطلب، ستظل الحبة في الذاكرة ما لم تنتهي مهلة الجلسة أو يغلق المستخدم المتصفح. سيؤدي هذا إلى استهلاك قدر معين من الذاكرة وزيادة عبء العمل على أداة تجميع البيانات المهملة JVM بشكل غير ضروري. ولذلك، فإن تحديد دورة الحياة الصحيحة للفاصوليا وتنظيفها في أسرع وقت ممكن بعد انتهاء مهمتها سيؤدي إلى تحسين أداء النظام.
بعض الطرق المفيدة الأخرى
: حاول عدم استخدام عامل التشغيل "+" في عمليات تسلسل السلسلة: في برمجة Java، غالبًا ما نستخدم عامل التشغيل "+" لتوصيل عدة سلاسل، ولكن ربما لم تفكر مطلقًا في أنه سيؤثر بالفعل على النظام الأداء، أليس كذلك؟ نظرًا لأن السلاسل النصية عبارة عن ثوابت، فسيقوم JVM بإنشاء بعض الكائنات المؤقتة. كلما زاد عدد "+" الذي تستخدمه، سيتم إنشاء المزيد من الكائنات المؤقتة، مما سيكون له أيضًا بعض التأثير على أداء النظام. الحل هو استخدام كائن StringBuffer بدلاً من عامل التشغيل "+".
· تجنب استخدام طريقة System.out.println(): نظرًا لأن System.out.println() عبارة عن مكالمة متزامنة، أي أنه عند الاتصال بها، يجب أن تنتظر عملية الإدخال/الإخراج على القرص حتى اكتمالها، لذا يجب أن نحاول تجنب استخدامه الاتصال. لكنها أداة لا غنى عنها ومريحة عندما نقوم بتصحيح أخطاء البرنامج. ولحل هذا التناقض، أقترح عليك استخدام أداة Log4j ( http://Jakarta.apache.org )، والتي يمكن أن تسهل تصحيح الأخطاء بدون طرق مثل System.out. سيتم إنشاء .println().
· المفاضلات بين ServletOutputStream وPrintWriter: قد يؤدي استخدام PrintWriter إلى بعض النفقات العامة الصغيرة، لأنه يحول كل المخرجات الأولية إلى تدفق أحرف للمخرجات، لذلك إذا تم استخدامه كمخرجات صفحة، فيجب على النظام أن يتحمل عملية تحويل. لا توجد مشكلة إذا كنت تستخدم ServletOutputStream كمخرج للصفحة، ولكن يتم إخراجه بشكل ثنائي. ولذلك، يجب الموازنة بين إيجابيات وسلبيات كل منهما في التطبيقات العملية.
ملخص
الغرض من هذه المقالة هو تحسين أداء تطبيقك بشكل كبير من خلال بعض تقنيات الضبط لـ servlets وJSP، وبالتالي تحسين أداء تطبيق J2EE بأكمله. من خلال تقنيات الضبط هذه، يمكنك أن تجد أنه ليس نظامًا أساسيًا تقنيًا معينًا (مثل النزاع بين J2EE و.NET) هو الذي يحدد أداء تطبيقك، المهم هو أن يكون لديك فهم أعمق لهذه المنصة، لذا عندها فقط يمكنك تحسين تطبيقك بشكل أساسي!