بنية مكدس البرامج التقليدية لتطبيقات Taobao عبر الإنترنت هي Nginx + Velocity + Java ، أي:
في هذا النظام ، يقوم Nginx بإعادة توجيه الطلب إلى تطبيق Java ، والذي يعالج المعاملة ويجعل البيانات في الصفحة النهائية باستخدام قالب السرعة.
بعد تقديم Node.js ، سنواجه حتما المشاكل التالية:
كيفية تصميم هيكل طوبولوجيا مكدس التكنولوجيا وكيفية اختيار طريقة النشر ، هل تعتبر علمية ومعقولة؟ بعد اكتمال المشروع ، كيفية تقسيم حركة المرور ، والتي هي مريحة وسريعة للتشغيل والصيانة؟ عند مواجهة مشاكل عبر الإنترنت ، كيفية القضاء على الخطر في أقرب وقت ممكن وتجنب خسائر أكبر؟ كيفية ضمان صحة التطبيق وإدارته على مستوى جدولة موازنة التحميل؟ طوبولوجيا النظام
وفقًا لتفكيرنا وممارستنا حول فصل النهايات الأمامية والخلفية (II) - بناءً على استكشاف القالب للنهايات الأمامية والخلفية ، يجب استبدال السرعة بـ Node.js ، بحيث يصبح هذا الهيكل:
هذا بالطبع الهدف المثالي. ومع ذلك ، فإن أول مقدمة من طبقة Node.js في المكدس التقليدي هي محاولة جديدة بعد كل شيء. لكي نكون آمنين ، قررنا تمكين تقنيات جديدة فقط على صفحة المفضلة (shoucang.taobao.com/item_collect.htm) من المفضلة لدينا ، بينما تستمر الصفحات الأخرى في استخدام الحلول التقليدية. أي أن NGINX يحدد نوع صفحة الطلب ويحدد ما إذا كان يتم إعادة توجيه الطلب إلى Node.js أو Java. لذلك ، أصبح الهيكل النهائي:
خطة النشر
يبدو أن الهيكل أعلاه على ما يرام ، ولكن في الواقع لا تزال المشكلة الجديدة تنتظر الجبهة. في الهيكل التقليدي ، يتم نشر Nginx و Java على نفس الخادم. يستمع Nginx إلى المنفذ 80 ويتواصل مع Java الاستماع إلى المنفذ 7001 في الجزء العلوي. الآن بعد أن تم تقديم Node.js ، هناك حاجة إلى عملية جديدة تحتاج إلى تشغيل منفذ استماع. هل يجب نشر node.js على نفس الجهاز باستخدام nginx + java ، أو يتم نشر node.js على مجموعة منفصلة؟
دعنا نقارن خصائص الطريقتين:
Taobao المفضلات هو تطبيق مع متوسط يومي PV لعشرات الملايين ، والتي لها متطلبات عالية للغاية للاستقرار (في الواقع ، عدم استقرار أي منتج عبر الإنترنت غير مقبول). إذا قمت بتبني نفس حل نشر الكتلة ، فأنت بحاجة فقط إلى توزيع الملفات مرة واحدة وإعادة التشغيل مرتين لإكمال الإصدار. في حال كنت بحاجة إلى التراجع ، تحتاج فقط إلى تشغيل حزمة خط الأساس مرة واحدة. من حيث الأداء ، فإن نشر المجموعة نفسه لديه أيضًا بعض المزايا النظرية (على الرغم من أن عرض النطاق الترددي للتبديل والكمون من الإنترانت متفائلون للغاية). أما بالنسبة لعلاقة واحدة أو كثيرة أو كثيرة ، فقد يتم استخدامها نظريًا بشكل كامل من قبل الخادم ، ولكن مقارنة بمتطلبات الاستقرار ، فإن هذه النقطة ليست ملحة للغاية. لذلك في تحول المفضلة ، اخترنا نفس حل نشر الكتلة.
رمادي
من أجل ضمان أقصى قدر من الاستقرار ، لم يزيل هذا التحول مباشرة رمز السرعة بالكامل. هناك ما يقرب من 100 خادم في مجموعة التطبيقات. نستخدم الخادم باعتباره التفاصيل ونقدم حركة المرور تدريجياً. بمعنى آخر ، على الرغم من أن عمليات Java + Node.js تعمل على جميع الخوادم ، سواء كانت هناك قواعد إعادة توجيه مقابلة على Nginx يحدد ما إذا كان طلب الحصول على مجموعة الأطفال على هذا الخادم سيتم معالجته من خلال Node.js. تكوين nginx هو:
location = "/Item_Collect.htm" {proxy_pass http://127.0.0.1:6001 ؛ # Node.js Process Port}الخوادم فقط التي أضافت قاعدة NGINX هذه ستسمح لـ NODE.JS التعامل مع الطلب المقابل. من خلال تكوين NGINX ، يكون مريحًا للغاية وسريعًا لزيادة حركة الرمادي وتقليلها ، والتكلفة منخفضة للغاية. إذا واجهت مشاكل ، يمكنك إعادة تكوين Nginx مباشرة ، والعودة على الفور إلى بنية مكدس التكنولوجيا التقليدية لتخفيف الخطر.
عندما أطلقناها لأول مرة ، قمنا بتمكين هذه القاعدة فقط على خادمين ، مما يعني أنه تتم معالجة أقل من 2 ٪ من حركة المرور عبر الإنترنت في Node.js ، ولا تزال طلبات حركة المرور المتبقية تقدم بالسرعة. في المستقبل ، ستزداد حركة المرور تدريجياً اعتمادًا على الموقف ، وأخيراً في الأسبوع الثالث ، سيتم تمكين جميع الخوادم. في هذه المرحلة ، يتم تقديم صفحات جمع المنتجات التي تحتوي على حركة مرور 100 ٪ في بيئة الإنتاج بواسطة Node.js (يمكنك التحقق من الرمز المصدر للبحث عن الكلمة الرئيسية Node.js).
يتغير
عملية الرمادي ليست سلسة. قبل قطع التدفق بالكامل ، واجهت بعض المشاكل ، سواء كانت كبيرة أو صغيرة. ترتبط معظم الأعمال بأعمال محددة ، وما يستحق التعلم منه هو فخ يتعلق بالتفاصيل الفنية.
فحص الصحة
في الهندسة المعمارية التقليدية ، سيبدأ نظام جدولة موازنة التحميل get على طلب كل ثانية إلى عنوان URL محدد على المنفذ 80 من كل خادم ، وتحديد ما إذا كان الخادم يعمل بشكل طبيعي بناءً على ما إذا كان رمز حالة HTTP الذي تم إرجاعه هو 200 . إذا تم طلب المهلة بعد 1s أو رمز حالة HTTP ليس 200 ، فلا يتم تقديم أي حركة مرور إلى الخادم لتجنب المشكلات عبر الإنترنت.
المسار إلى هذا الطلب هو nginx -> java -> nginx ، مما يعني أنه طالما تم إرجاع 200 ، فإن nginx و java من هذا الخادم في حالة صحية. بعد تقديم node.js ، يصبح هذا المسار nginx -> node.js -> java -> node.js -> nginx. الرمز المقابل هو:
var http = require ('http') ؛ app.get ('/status.taobao' ، function (req ، res) {http.get ({host: '127.1' ، port: 7001 ، path: '/status.taobao'} ، function (res) {res.send (res.StatusCode) ؛ }) ؛ومع ذلك ، أثناء عملية الاختبار ، تبين أنه عندما تقوم Node.js بإعادة توجيه هذه الطلبات ، استغرق الأمر عدة ثوان أو حتى عشر ثوانٍ للحصول على عودة Java Side مرة كل ست أو سبع مرات. سيؤدي ذلك إلى اعتقاد نظام جدولة موازنة التحميل أن الخلل حدث على الخادم ثم قطع حركة المرور ، ولكن في الواقع ، يمكن أن يعمل الخادم بشكل طبيعي. من الواضح أن هذه مشكلة كبيرة.
بعد البحث ، وجدت أنه افتراضيًا ، ستستخدم Node.js فئة HTTP Agent لإنشاء اتصالات HTTP. هذه الفئة تنفذ تجمع توصيل المقبس. الحد الأعلى الافتراضي لعدد الاتصالات لكل زوج من منفذ مضيف + هو 5. في الوقت نفسه ، تتضمن الطلبات التي تم بدءها من قبل فئة HTTP Agent Connection: Keep-Alive افتراضيًا ، مما يؤدي إلى عدم إصدار الاتصال الذي تم إرجاعه في الوقت المناسب ، ولا
هناك ثلاثة حلول نهائية:
تعطيل HTTP Agent ، أي إضافة agent: false عند استدعاء طريقة get ، والرمز النهائي هو:
var http = require ('http') ؛ app.get ('/status.taobao' ، function (req ، res) {http.get ({host: '127.1' ، المنفذ: 7001 ، الوكيل: خطأ ، المسار: '/stats.taobao'} ، function (res) {res.send (res.StatusCode) ؛ Res.Send (404) ؛ اضبط الحد الأعلى لعدد المقبس العالمي لكائنات http :
http.globalagent.maxssockets = 1000 ؛
عند عودة الطلب ، يتم فصله في الوقت المناسب والاستبدال:
http.get (الخيارات ، الدالة (res) {}). on ("socket" ، function (socket) {socket.emit ("AgentRemove") ؛ // استمع إلى أحداث المقبس وأحداث Dispatch AgentRemove في رد الاتصال}) ؛في الممارسة العملية ، اخترنا الطريقة الأولى. بعد هذا التعديل ، لم يتم العثور على مشاكل أخرى في الفحص الصحي.
يجمع
بدأت ممارسة الجمع بين Node.js وسيناريوهات الأعمال التقليدية للتو ، ولا يزال هناك الكثير من نقاط التحسين التي تستحق الاستكشاف بعمق. على سبيل المثال ، بعد أن تكون تطبيقات Java مركزية تمامًا ، هل يمكنك إجراء اختبار نشر الكتلة لتحسين استخدام الخادم؟ أو ، هل يمكن أن تكون أساليب الإصدار والتراجع أكثر مرونة ويمكن التحكم فيها؟ جميع التفاصيل تستحق المزيد من البحث.