"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > من Node.js إلى Go: زيادة التحميل الزائد لآلاف الملفات في ملف مضغوط واحد

من Node.js إلى Go: زيادة التحميل الزائد لآلاف الملفات في ملف مضغوط واحد

تم النشر بتاريخ 2024-08-24
تصفح:244

From Node.js to Go: Supercharging Sownloads of Thousands of Files as a Single Zip

كمطورين، غالبًا ما نواجه تحديات عند التعامل مع معالجة البيانات وتسليمها على نطاق واسع. في Kamero، عالجنا مؤخرًا اختناقًا كبيرًا في مسار تسليم الملفات لدينا. يتيح تطبيقنا للمستخدمين تنزيل آلاف الملفات المرتبطة بحدث معين كملف مضغوط واحد. كانت هذه الميزة، المدعومة بوظيفة Lambda المستندة إلى Node.js والمسؤولة عن جلب الملفات وضغطها من مجموعات S3، تعاني من قيود الذاكرة وأوقات التنفيذ الطويلة مع نمو قاعدة المستخدمين لدينا.

يعرض هذا المنشور تفاصيل رحلتنا من تطبيق Node.js المتعطش للموارد إلى حل Go بسيط وسريع للغاية يتعامل بكفاءة مع تنزيلات S3 الضخمة. سنستكشف كيف قمنا بتحسين نظامنا لتزويد المستخدمين بتجربة سلسة عند طلب أعداد كبيرة من الملفات من أحداث معينة، وكلها مجمعة في ملف مضغوط واحد مناسب للتنزيل.

التحدي

واجهت وظيفة Lambda الأصلية العديد من المشكلات الحرجة عند معالجة مجموعات كبيرة من الملفات المستندة إلى الأحداث:

  1. استهلاك الذاكرة: حتى مع وجود 10 جيجابايت من الذاكرة المخصصة، قد تفشل الوظيفة عند معالجة 20000 ملف للأحداث الأكبر.
  2. وقت التنفيذ: كانت عمليات الضغط للأحداث التي تحتوي على العديد من الملفات تستغرق وقتًا طويلاً جدًا، وفي بعض الأحيان تنتهي مهلة التنفيذ قبل الانتهاء.
  3. قابلية التوسع: لم تتمكن الوظيفة من التعامل مع التحميل المتزايد بكفاءة، مما يحد من قدرتنا على خدمة المستخدمين بمجموعات ملفات كبيرة من الأحداث الشائعة.
  4. تجربة المستخدم: أثرت أوقات إعداد التنزيل البطيئة على رضا المستخدم، خاصة بالنسبة للأحداث التي تحتوي على عدد كبير من الملفات.

تنفيذ Node.js: نظرة سريعة

استخدم تطبيقنا الأصلي مكتبة s3-zip لإنشاء ملفات مضغوطة من كائنات S3. إليك مقتطف مبسط لكيفية معالجة الملفات:

const s3Zip = require("s3-zip");

// ... other code ...

const body = s3Zip.archive(
  { bucket: bucketName },
  eventId,
  files,
  entryData
);

await uploadZipFile(Upload_Bucket, zipfileKey, body);

أثناء نجاح هذا الأسلوب، تم تحميل جميع الملفات في الذاكرة قبل إنشاء الملف المضغوط، مما أدى إلى استخدام مرتفع للذاكرة وأخطاء محتملة في نفاد الذاكرة لمجموعات الملفات الكبيرة.

أدخل Go: إعادة كتابة لتغيير قواعد اللعبة

قررنا إعادة كتابة وظيفة Lambda الخاصة بنا في Go، مع الاستفادة من كفاءتها وميزات التزامن المضمنة فيها. وكانت النتائج مذهلة:

  1. استخدام الذاكرة: انخفض من 10 جيجابايت إلى 100 ميجابايت فقط لنفس حمل العمل.
  2. السرعة: أصبحت الوظيفة أسرع بحوالي 10 مرات.
  3. الموثوقية: تمت معالجة 20000 ملف بنجاح دون مشاكل.

التحسينات الرئيسية في تنفيذ Go

1. عمليات S3 الفعالة

لقد استخدمنا AWS SDK لـ Go v2، والذي يوفر أداءً أفضل واستخدامًا أقل للذاكرة مقارنةً بالإصدار 1:

cfg, err := config.LoadDefaultConfig(context.TODO())
s3Client = s3.NewFromConfig(cfg)

2. المعالجة المتزامنة

أتاحت لنا إجراءات Go معالجة ملفات متعددة في وقت واحد:

var wg sync.WaitGroup
sem := make(chan struct{}, 10) // Limit concurrent operations

for _, photo := range photos {
    wg.Add(1)
    go func(photo Photo) {
        defer wg.Done()
        sem 



يسمح لنا هذا الأسلوب بمعالجة ملفات متعددة في وقت واحد مع التحكم في مستوى التزامن لمنع إرباك النظام.

3. إنشاء الرمز البريدي المتدفق

بدلاً من تحميل جميع الملفات في الذاكرة، نقوم بدفق المحتوى المضغوط مباشرةً إلى S3:

pipeReader, pipeWriter := io.Pipe()

go func() {
    zipWriter := zip.NewWriter(pipeWriter)
    // Add files to zip
    zipWriter.Close()
    pipeWriter.Close()
}()

// Upload streaming content to S3
uploader.Upload(ctx, &s3.PutObjectInput{
    Bucket: &destBucket,
    Key:    &zipFileKey,
    Body:   pipeReader,
})

يؤدي أسلوب البث هذا إلى تقليل استخدام الذاكرة بشكل كبير ويسمح لنا بالتعامل مع مجموعات ملفات أكبر بكثير.

النتائج

أدت إعادة الكتابة إلى Go إلى تحسينات مذهلة:

  1. استخدام الذاكرة: تم تقليله بنسبة 99% (من 10 جيجابايت إلى 100 ميجابايت)
  2. سرعة المعالجة: تمت زيادتها بنسبة 1000% تقريبًا
  3. الموثوقية: التعامل بنجاح مع 20000 ملف دون مشاكل
  4. فعالية التكلفة: يؤدي استخدام الذاكرة الأقل ووقت التنفيذ الأسرع إلى تقليل تكاليف AWS Lambda

الدروس المستفادة

  1. اختيار اللغة مهم: أحدث نموذج الكفاءة والتزامن في Go فرقًا كبيرًا في حالة الاستخدام لدينا.
  2. فهم الاختناقات التي تواجهك: ساعدنا تحديد وظيفة Node.js في تحديد المجالات الرئيسية للتحسين.
  3. الاستفادة من الحلول السحابية الأصلية: استخدام AWS SDK for Go v2 وفهم قدرات S3 يسمح بتكامل وأداء أفضل.
  4. التفكير في التدفقات: تعد معالجة البيانات كتدفقات بدلاً من تحميل كل شيء في الذاكرة أمرًا بالغ الأهمية للعمليات واسعة النطاق.

خاتمة

إن إعادة كتابة وظيفة Lambda الخاصة بنا في Go لم تحل مشكلات التوسع الفورية لدينا فحسب، بل قدمت أيضًا حلاً أكثر قوة وفعالية لاحتياجات معالجة الملفات لدينا. على الرغم من أن Node.js خدمنا جيدًا في البداية، إلا أن هذه التجربة سلطت الضوء على أهمية اختيار الأداة المناسبة للمهمة، خاصة عند التعامل مع المهام كثيفة الاستخدام للموارد على نطاق واسع.

تذكر أن أفضل لغة أو إطار عمل يعتمد على حالة الاستخدام المحددة لديك. في السيناريو الخاص بنا، تتوافق خصائص أداء Go تمامًا مع احتياجاتنا، مما يؤدي إلى تحسين تجربة المستخدم بشكل كبير وتقليل تكاليف التشغيل.

هل واجهت تحديات مماثلة مع الوظائف بدون خادم؟ كيف تغلبت عليهم؟ نود أن نسمع عن تجاربك في التعليقات أدناه!

بيان الافراج تم إعادة إنتاج هذه المقالة على: https://dev.to/hiteshsisara/from-nodejs-to-go-supercharging-s3-downloads-of-thousands-of-files-as-a-single-zip-474b?1إذا كان هناك في حالة وجود أي انتهاك، يرجى الاتصال بـ [email protected] للحذف
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3