المدونة

لماذا يصبح عرض PDF عند Edge مهمًا بعد 10 آلاف فاتورة يوميًا

بعد حجم معين، تتغير حسابات cold start وزمن الوصول الإقليمي وحوسبة كل صفحة. نظرة عملية على اللحظة التي يتوقف فيها Edge rendering عن كونه فكرة لطيفة ويبدأ بدفع تكلفته.

إذا كنت تولد بضع مئات من ملفات PDF يوميًا من Lambda واحدة أو pod صغير في Kubernetes، فلن تكون البنية هي العامل الحاسم. أي شيء تقريبًا سيعمل. وأي شيء سيكون سريعًا بما يكفي.

لكن الصورة تتغير عند الحجم. بمجرد أن تبدأ بإخراج عشرات الآلاف من المستندات يوميًا، وهذا ينطبق تقريبًا على أي منصة تجارة إلكترونية، أو شركة لوجستية، أو خدمة BNPL، أو مزود رواتب، أو منصة فوترة لديها traction متواضع، تبدأ ثلاثة أرقام في الضغط عليك:

  1. زمن البدء البارد، لأن هناك دائمًا بيئة تشغيل باردة في مكان ما.
  2. زمن الوصول الجغرافي، لأن العملاء ليسوا بجانب خادمك الأصلي.
  3. تكلفة الحساب لكل توليد، لأنها تتكرر آلاف المرات يوميًا.

يمر هذا المقال على كيفية تغير هذه الأرقام بعد نحو 10K render/day، ولماذا تكون العارضات المنشورة عند Edge مثل gPdf فئة مختلفة من الحلول، لا “الفكرة نفسها لكن أسرع”.

1. ضريبة البدء البارد تكبر مع التزامن

البدء البارد ليس طلبا بطيئا عابرا؛ إنه مرتبط بشكل منحنى التزامن:

  • تحتفظ بعشرة حاويات دافئة بناء على متوسط الزيارات.
  • تأتي زيادة 3× في الزيارات: Black Friday، يوم رواتب، نهاية ربع.
  • تبدأ 20 حاوية جديدة لاستيعاب الذروة.
  • كل حاوية تحتاج 1.5 إلى 2.5 ثانية لتشغيل Chromium أو Prince أو بيئة التشغيل الخاصة بك.
  • خلال تلك الفترة يرتفع p99، وقد يستهلك توليد PDF معظم ميزانية timeout في مسار الطلب.

هذا مقبول عندما يكون الحمل ثابتا. لكنه قاس عندما يكون الحمل متقطعا، وهذا هو نمط PDF بطبيعته: الفواتير عند دورات الفوترة، ملصقات الشحن عند الاستلام، والكشوف في نهاية الشهر.

البديل عند Edge: يبدأ Cloudflare Worker isolate خلال 5-20 ms، لا خلال 1.5-2.5 ثانية. لا توجد حاوية لتدويرها، ولا JVM/V8 لتهيئته، ولا متصفح لإقلاعه؛ تُحمّل وحدة WASM داخل process موجود أصلًا. عمليًا، لا يعود cold start شيئًا تبني حوله.

في gPdf تحديدًا، أسوأ cold start رصدناه في benchmarks يقارب 12 ms، وهذا فقط لأول طلب إلى isolate مُعيّن حديثًا. الطلبات اللاحقة على isolate نفسه تتجاوز حتى ذلك.

2. زمن الوصول الجغرافي حقيقي حتى لو كان التوليد سريعا

الرحلة من سيدني إلى us-east-1 قد تضيف 200 ms قبل أن يبدأ كودك. من ساو باولو إلى eu-west-1 حوالي 190 ms. ومن مومباي إلى شرق الولايات المتحدة حوالي 220 ms.

إذا كانت API مركزية تولد PDF خلال 300 ms، فالصورة من سيدني تبدو هكذا:

client -> us-east  : 200 ms
us-east render     : 300 ms
us-east -> client  : 200 ms
total wall-clock   : 700 ms

قد لا يهم ذلك في jobs خلفية كبيرة، لكنه مؤلم في تدفق تفاعلي مثل معاينة الفاتورة قبل إرسالها.

البديل على الحافة: تعمل Cloudflare في مئات المدن. أقرب colo إلى عميل سيدني قد يكون على بعد 5 ms:

client -> SYD colo : 5 ms
SYD render         : 4 ms
SYD -> client      : 5 ms
total wall-clock   : 14 ms

هذا تحسن 50× في التدفقات التفاعلية. في jobs الخلفية قد يكون الأثر محدودًا، لكن معاينات PDF التفاعلية مثل “أرني كيف تبدو الفاتورة قبل الإرسال” تصبح مجانية الشعور بدل أن تكون متقطعة.

الفائدة المخفية من الدرجة الثانية: إذا كانت PDF API تعمل عند Edge، يمكنك نقل منطق مجاور إليها أيضًا: معاينة PDF في checkout، وrate limit، وفحص auth. كل جزء تدفعه إلى Edge يزيل round-trip من المسار الساخن.

3. تكلفة كل توليد تتراكم بصمت

عند 100,000 توليد يوميًا:

  • Puppeteer عند ~600 ms وذاكرة 1024 MB: حوالي 240 دولارًا/شهر للحساب فقط، قبل egress والتشغيل.
  • DocRaptor بسعر $89 لكل 100,000 صفحة: حوالي 2,670 دولار/شهر عند 3 ملايين صفحة شهريًا.
  • gPdf بسعر 5 لكل 100,000 صفحة: حوالي **150 دولارًا/شهر** عند 100,000 يوميًا، أو 5 تقريبًا إذا كان حجمك 100,000 شهريًا فقط.

عند 1 مليون توليد يوميًا تتسع الفجوة:

  • Puppeteer: حوالي 2,400 دولار/شهر مع التشغيل والمناوبة.
  • DocRaptor: حوالي 26,700 دولار/شهر.
  • gPdf: حوالي 1,500 دولار/شهر وفق نفس منطق السعر الحجمي.

رد الفعل الشائع هو: “لا بد أن الوفورات أصغر عمليًا؛ هناك شيء مخفي.” في تجربتنا، لا. محرك التكلفة في إنشاء PDF هو footprint الحوسبي للعارض. عندما تستبدل عملية Chromium بحجم 600 MB بوحدة WASM بحجم 4 MB، تنخفض كلفة كل render بنحو 100×، ويتبعها الفاتورة.

والسبب في أن هذا يعمل دون أن نخسر نحن المال: سعر Cloudflare Workers Bundled الأساسي يقارب $0.50 لكل مليون طلب. ومع عارض يستخدم نحو 1.5 ms من CPU لكل call، تصبح cost-of-goods-sold لكل render فعلًا أقل من cent. نضيف هامشًا متواضعًا للوصول إلى business مستدام، وتبقى أنت ترى فجوة 18×.

ما الذي يشتريه Edge deployment فعليًا

زمن استجابة يمكن توقعه تحت الضغط

عندما لا توجد تكلفة إقلاع لكل طلب، يبقى p50 وp99 قريبين. نرى عادة p99 ضمن 3× من p50 حتى أثناء ذروة traffic، مقارنة بـ Puppeteer حيث قد يصل p99 إلى 10× p50 أثناء عواصف cold start.

ملف تشغيل واحد في كل مكان

وحدة .wasm تُنشر بالشكل نفسه إلى كل Cloudflare colo. لا يوجد سؤال “هل pool سيدني دافئ؟”؛ كل isolate يشغّل الوحدة خلال milliseconds ويخدم بالطريقة نفسها. هذا أبسط تشغيليًا من إدارة حجوزات regional Lambda concurrency.

طريق إلى التشغيل داخل بيئة العميل

إذا أردت يومًا تشغيل gPdf داخل حدود عميل، في VPC لديه أو cluster معزول أو intranet air-gapped، فالوحدة نفسها تعمل. هذا هو الفرق بين “استضفنا SaaS” و“شحنّا تقنية تعمل في أي مكان“.

أين لا يكون Edge سحرًا

  • Renders متعددة الثواني. إذا كان PDF واحد يستغرق 30 ثانية، مثل قوائم مالية ضخمة أو تقارير علمية، فحاوية طويلة العمر ذات حالة persistent أفضل من مقاتلة CPU caps عند Edge.
  • Renders تحتاج قواعد بيانات أخرى. إذا كان render يحتاج JOIN لثلاث جداول OLAP، فضع العارض قرب قاعدة البيانات، لا عند Edge. الحل العملي: نفّذ JOIN ثم أرسل JSON النهائي إلى Edge للعرض الفعلي.
  • مخرجات تحتاج post-processing. Watermarking، التوقيع، الأرشفة؛ إذا كان مسار ما بعد العرض متعدد الخطوات وstateful، قد تصبح خاصية stateless في Edge كلفة بدل ميزة.

في كل ما عدا ذلك، وهو الغالبية العظمى من traffic فواتير وملصقات وإيصالات B2B، يفوز Edge في كل محور مهم.

متى تتوقف عن قبول الوضع الحالي

إذا انطبقت ثلاث نقاط، فقد حان وقت التجربة:

  • تكلفة بنية PDF تتجاوز 300 دولار/شهر.
  • p99 لتوليد PDF يتجاوز 800 ms في traffic عادي.
  • واجهت حادث cold start أثر على العملاء.
  • قضيت أكثر من 4 ساعات في مشاكل CJK أو RTL أو emoji glyphs.
  • تولد PDF داخل تدفق تفاعلي.
  • تعمل في أكثر من منطقة جغرافية.

النقاط الثلاث الأولى تعني أنك تدفع أكثر وتقبل latency أسوأ. النقاط التالية تعني أن العارض المركزي يحد من المنتج نفسه.

إذا بدا هذا مألوفًا، فإن Playground يولد فاتورة تجريبية في المتصفح خلال أقل من 5 ms. دعه يتكلم بالأرقام.