عندما يقوم مستخدم بالإبلاغ عن مشكلة: عندما يحدث خطأ عند استخدام وظيفة معينة عبر الإنترنت، كيف يمكن تحديد موقعه بسرعة ودقة؟ كيف يمكن تتبع التحسين بشكل فعال عندما تقوم واجهة طلب معينة بإرجاع البيانات ببطء؟
كما نعلم جميعًا، عندما يأتي طلب، من المحتمل أن يتم إنشاء السجلات التالية:
1. AceesLog: سجل وصول المستخدم
2. الاستثناء: سجل استثناء التعليمات البرمجية
3. SQL: سجل استعلام SQL
4. الطرف الثالث: ثالث-
سجلخدمة الطرف
كيفية تتبع جميع السجلات التي تم إنشاؤها بواسطة الطلب؟
تتمثل الطريقة العامة في استخدام معرف الطلب كمعرف فريد،
ثم كتابة برنامج وسيط لإدخال معرف الطلب في السياق، عندما يلزم إجراء التسجيل، أخرجه من السياق للطباعة
في خدمات الجهات الخارجية وسجلات SQL ، تحتاج أيضًا إلى إدخال معرف الطلب في السياق، ويتم تمرير معرف الطلب إلى الوظيفة المقابلة للطباعة، ومن المزعج جدًا تمريره طبقة تلو الأخرى، كما أن الكود متطفل نسبيًا.
هدفنا هو تقليل تطفل الكود وحقنه مرة واحدة وتتبعه تلقائيًا.
بعد البحث، يمكن لـ async_hooks تتبع دورة حياة السلوك غير المتزامن في كل مورد غير متزامن (كل طلب هو مورد غير متزامن)، وله معرفان،
وهما asyncId (معرف دورة الحياة الحالية للمورد غير المتزامن)، وtrigerAsyncId (المورد غير المتزامن الأصلي). بطاقة تعريف).
يوفر async_hooks خطافات دورة الحياة التالية للاستماع إلى الموارد غير المتزامنة:
asyncHook = async_hook.createHook({ // استمع إلى إنشاء الموارد غير المتزامنة init(asyncId,type,triggerAsyncId,resource){}, // قبل أن يبدأ تنفيذ وظيفة رد الاتصال للمورد غير المتزامن before(asyncId){}, // بعد بدء تنفيذ وظيفة رد الاتصال للمورد غير المتزامن، after(asyncId){}, // مراقبة تدمير الموارد غير المتزامنة Destroy(asyncId){} })
ثم إذا قمنا بإجراء تعيين، فسيتم تعيين كل معرف غير متزامن إلى وحدة تخزين، ويتم تخزين معرف الطلب المقابل في وحدة التخزين، فيمكن الحصول على معرف الطلب بسهولة.
لقد حدث أن مكتبة cls-hooked قد تم تغليفها بناءً على async_hooks، مع الاحتفاظ بنسخة من البيانات في نفس المورد غير المتزامن وتخزينها في شكل أزواج قيمة المفتاح. (ملاحظة: يجب استخدام async_hooked في إصدار أعلى من العقدة> = 8.2.1) بالطبع، هناك تطبيقات أخرى في المجتمع، مثل cls-session، وnode-continuation-local-storage، وما إلى ذلك.
لنتحدث عن مثال لاستخدام cls-hooked في مشروعي:
/session.js إنشاء مساحة تخزين مسماة
const createNamespace = require('cls-hooked').createNamespace جلسة const = createNamespace('requestId-store') Module.exports = جلسة
طباعة سجل الجلسة /logger.js
const session = require('./session') وحدة التصدير = { معلومات: (رسالة) => { معرف طلب const = session.get('requestId') console.log(`requestId:${requestId}`، رسالة) }, خطأ: (الرسالة) => { معرف طلب const = session.get('requestId') console.error(`requestId:${requestId}`، رسالة) } }
/sequelize.js SQL يستدعي المسجل لطباعة السجلات
const logger = require("./logger") جديدSequelize( التسجيل: الوظيفة (sql، costtime) { logger.error( `sql exe : ${sql} | costtime ${costtime} ms` ); } )
/app.js قم بتعيين معرف الطلب، وقم بتعيين معرف الطلب لإرجاع رأس الاستجابة، وسجل الوصول إلى الطباعة
const session = require('./session') مسجل ثابت = يتطلب ('./مسجل') الوصول إلى وظيفة غير متزامنة (ctx، التالي) { const requestId = ctx.header['x-request-id'] ||. معلمات const = ctx.request.body ؟ JSON.stringify(ctx.request.body) : JSON.stringify(ctx.request.query) // تعيين معرف الطلب session.run(() => { session.set('requestId', requestId) logger.info(`url:${ctx.request.path}; params:${params}`) next() // قم بتعيين رأس استجابة الإرجاع ctx.res.setHeader('X-Request-Id',requestId) }) }
دعونا نلقي نظرة على السجل عندما يكون مسار الطلب هو /home?a=1:
سجل الوصول: معرف الطلب:79f422a6-6151-4bfd-93ca-3c6f892fb9ac url:/home;params:{"a":":1"} سجل SQL: معرف الطلب:79f422a6-6151-4bfd-93ca-3c6f892fb9ac SQL إكس: تم التنفيذ (افتراضي): SELECT `id` FROM t_user
يمكنك أن ترى أن معرف طلب السجل للارتباط بأكمله لنفس الطلب هو نفسه. إذا تم إرسال إنذار لاحقًا إلى منصة الإنذار، فيمكننا العثور على الرابط بأكمله الذي تم تنفيذه بواسطة هذا الطلب بناءً على معرف الطلب.
قد يلاحظ الطلاب الحذرون أنني قمت أيضًا بتعيين معرف الطلب في رأس الاستجابة الذي تم إرجاعه بواسطة الواجهة. والغرض من ذلك هو أنه إذا تم العثور على طلب يستجيب ببطء أو به مشكلات، فيمكن معرفة معرف الطلب مباشرةً من المتصفح وتحليله.
لقد أجريت اختبار التحمل محليًا،
وهذه هي مقارنة استخدام الذاكرة:
حوالي 10% أكثر من عدم استخدام async_hook.
لا بأس بالنسبة لنظام QPS الخاص بنا بنظام 100 مستوى، ولكن إذا كانت خدمة متزامنة للغاية، فقد نحتاج إلى النظر فيها بعناية.
ملاحظة: إذا كان هناك أي أخطاء، يرجى الإشارة إليها إذا لم تعجبك، يرجى عدم التعليق.