أطلقت Cloudflare خدمة K2 كنسخة Public Beta في 1 أكتوبر 2026 بوصفها Primitive Serverless لتدفق الأحداث الدائم. يضيف Producers دفعات إلى سجل مرتب، وتقرأ Subscriptions مستقلة السجلات المحتفظ بها حسب سرعتها. وتقول Cloudflare إن K2 يخزن مقاطع السجل المقسمة فوق R2 Object Storage بدل تشغيل Broker Cluster تقليدي يعتمد على أقراص محلية.
هذه المعمارية هي أهم ما في الإطلاق. K2 ليس «Kafka بلا خوادم» في كل سلوكياته، وليس بديلًا أسرع من Task Queue. نقل المتانة إلى Object Storage يغيّر نموذج التشغيل وشكل التكلفة والحد الأدنى للزمن وأنماط الفشل. لذلك يجب أن يبدأ تقييم K2 من هذه العقود، لا من سهولة إنشاء Stream بأمر واحد.
الخدمة متاحة حاليًا كـPublic Beta لحسابات Workers Paid. وتوثق Cloudflare حد تخزين 10 GB للحساب أثناء Beta، وRetention قابلة للضبط من ساعة إلى 30 يومًا، وعدم احتساب رسوم استخدام خلال Beta. تجعلها هذه الحقائق مناسبة للتقييم، لا لهجرة تلقائية للإنتاج.
ما الذي أطلقته Cloudflare فعليًا؟
يعرّف دليل K2 الـStream بوصفه Durable Log. يكتب Producer السجلات، ويحتفظ بها Stream لمدة محددة، وتتبع Subscription واحدة أو أكثر مواضع مستقلة داخل السجل. يمكن لـSubscription توزيع الدفعات على مجموعة Workers، بينما تسمح Subscriptions منفصلة لعدة تطبيقات برؤية السجلات نفسها بصورة مستقلة.
يحمل Record محتوى Binary وHeaders نصية اختيارية. يرسل Producers السجلات على شكل Batches، وينص عقد Produce على أن كتابة الدفعة Atomic: إما أن تُخزن كل السجلات أو لا يُخزن أي منها. ويمكن الإنتاج عبر HTTP Endpoint أو Workers Binding.
يسحب Consumers البيانات من Subscription. يمنح K2 الدفعة إلى Worker ضمن Lease مدتها خمس دقائق. يستطيع Worker إرسال Ack أو Nack لإعادة التسليم أو تمديد Lease. وإذا انتهت Lease قبل Ack، يمكن أن يعيد K2 تسليم السجلات. لذلك توثق Cloudflare ضمان At-least-once، لا Exactly-once.
يتحكم هذا الفرق في تصميم Consumer. يثبت نجاح رد Producer أن K2 قبل الدفعة؛ لكنه لا يثبت أن كل قاعدة بيانات أو Warehouse أو API في الخلفية طبقت كل سجل مرة واحدة.
لماذا يختلف السجل المبني فوق Object Storage؟
تحتفظ Brokers التقليدية غالبًا بمقاطع السجل النشطة قرب Compute، ثم تنسخها بين Nodes. أما K2 فيستخدم R2 كطبقة الحالة الدائمة. تصف Cloudflare عمليات R2 بأنها دائمة وStrongly Consistent، ما يسمح بدفع مسؤوليات Replication وConsensus إلى طبقة التخزين وتبسيط طبقة التطبيق.
لا تدعم Object Stores إلحاق Bytes إلى Object موجود مثل Log File محلي. يجمع K2 الكتابات مؤقتًا في الذاكرة، وينتظر فترة قصيرة لتكوين Batch، ثم يكتب Segment كاملًا. ويستخدم عمليات R2 الذرية لإسناد Offsets متزايدة من دون Coordination Service منفصلة.
يقدم ذلك فصلًا مفيدًا: يمكن أن تكون Compute مؤقتة وتتوسع بصورة مستقلة عن البيانات المحتفظ بها، ويمكن تخزين التاريخ في طبقة مصممة للمتانة والسعة بدل Broker Fleet محجوزة دائمًا. كما لا يتطلب تعطل Consumer بقاء Producer متصلًا به.
المقابل هو Latency. تقول Cloudflare إن الإصدار الأول يضيف قرابة ثانية واحدة عند p99 لعملية Produce بسبب انتظار Batch وكتابتها إلى Object Storage. هذا رقم أعلنته الشركة لمعمارية Beta، وليس Benchmark مستقلًا أو وعدًا لكل Workload.
إذًا القرار ليس «Managed أم Self-hosted». القرار هو: هل تستفيد Workload من المتانة Serverless والاحتفاظ وFan-out أكثر مما تتضرر من زمن الكتابة الأعلى وسطح تشغيلي ما زال جديدًا؟
لا تخلط Stream مع Task Queue
تضع Cloudflare خدمة Queues حول وحدات عمل فردية غير متزامنة. تقدم Queue خصائص موجهة للرسالة مثل Retries وDelays وDead-letter handling. أما K2 فمصمم لنقل البيانات بكثافة، والاحتفاظ بالتاريخ، وFan-out عبر Subscriptions. يعالج Batches بكفاءة، لكن على حساب التحكم بكل رسالة منفردة.
استخدم Task Queue عندما يمثل العنصر عملًا يجب أن ينجح أو يفشل أو يعاد أو ينتقل إلى Dead-letter بصورة مستقلة؛ مثل إنشاء PDF لفاتورة أو تغيير حجم صورة. واستخدم Retained Stream عندما يحتاج عدة Consumers إلى تاريخ مرتب أو Replay أو تقدم مستقل؛ مثل Product Analytics أو Audit Events أو Change Propagation أو بيانات مراقبة النماذج.
Basin Pipelines مختلفة أيضًا. توصي Cloudflare باستخدام Pipelines عندما تكون الوجهة R2 أو Iceberg Table ويكون الهدف الأساسي Ingestion وTransformation. ويصبح K2 Primitive أعم عندما تنفذ Consumers معالجة مخصصة أو تكتب إلى وجهات أخرى.
هذه الحدود مهمة لأن تبني Stream لا يلغي Workflow Semantics. إذا احتاج حدث طلب إلى Compensation وTimeout Ownership وBusiness State Machine، تبقى هذه المسؤوليات داخل التطبيق.
ضمان At-least-once يحتاج Consumers مقاومة للتكرار
يحذر دليل البدء مع K2 صراحة من أن K2 لا ينفذ Deduplication. يمكن لـRetry من Producer أن يخزن الحدث المنطقي نفسه أكثر من مرة. ويمكن أن يستقبل Consumer الدفعة المؤجرة مجددًا بعد فقدان Response أو انتهاء Lease أو Nack.
لذلك يحتاج كل Business Event إلى event_id ثابت يُنشأ قبل أول محاولة Produce. ويجب أن يحتوي Payload أيضًا event type وschema version وaggregate identifier وoccurred_at وهوية Producer. يمكن أن تساعد Headers في Routing، لكن Sink الدائمة يجب أن تفرض Idempotency.
مع Relational Sink، أدخل event_id في Inbox Table عليها Unique Constraint داخل Transaction نفسها التي تطبق Projection. إذا حدث Conflict، تعامل مع الحدث على أنه معالج سابقًا. ومع External API، استخدم Idempotency Key الخاصة بالمزود عند توفرها، واحتفظ بـOutbox أو Result Ledger محليًا. مفتاح Deduplication داخل Cache وحدها لا يكفي عندما تكون TTL أقصر من Retention أو Replay.
لا ترسل Ack للدفعة إلا بعد أن تصبح كل الآثار المقبولة Durable. وإذا احتوت Batch سجلًا واحدًا غير صالح، فقد يحبس Retry الأعمى للدفعة كلها السجلات السليمة خلف Poison Event. لا يعلن K2 عن Dead-letter على مستوى الرسالة في هذا العقد، لذلك يجب أن يتحقق Consumer من كل Record، ويعزل الفشل الدائم في مخزن خاص، ويجعل قرار الدفعة صريحًا.
تحدد Leases عقد التزامن
تعرّف كل عملية Consume قيمة worker_id. يمنح K2 الدفعة لذلك Worker ضمن Lease، وينص دليل Consumer على أن Worker واحدًا يمكنه الاحتفاظ بـLease واحدة. وتدعم Subscription حتى 128 Active Leases ضمن حدود Beta الحالية.
إذا احتاجت المعالجة إلى أكثر من خمس دقائق، مدّد Lease قبل انتهائها. وإذا أعاد التمديد Conflict لأن Worker لم يعد يملك Lease، أوقف تطبيق Side Effects واطلب Batch جديدة. الاستمرار بعد فقدان Lease قد يتسابق مع Worker ثانٍ يعالج السجلات المعاد تسليمها.
يجب أن يتبع Autoscaling إشارات مفيدة: السجلات المتاحة، ومدة المعالجة، واستخدام Leases، ومعدل Redelivery، وزمن Sink، وتصنيفات الأخطاء. لا يخبر CPU وحده إن كانت زيادة Workers مفيدة. قد تصبح قاعدة بيانات مشتركة بطيئة أقل موثوقية إذا توسعت مجموعة Consumers بعنف.
اجعل worker_id فريدًا لكل Process فعالة وثابتًا طوال عمر الطلب الجاري. إعادة استخدام معرف واحد بين Replicas تدمج ملكية Leases. وإنشاء معرف جديد في كل Retry يصعّب استعادة الرد، لأن K2 يعيد الدفعة المؤجرة إلى Worker نفسها.
السجل المرتب لا يعني آثارًا مرتبة
يصف K2 الـStream بأنه مرتب ويمنح Offsets متزايدة. لكن ذلك لا يعني أن Parallel Consumers تُنهي العمل حسب ترتيب Offset. توضح الوثائق أن K2 لا يضمن ترتيب المعالجة بين Workers يشتركون في Subscription واحدة.
إذا كان الترتيب مهمًا لعميل أو حساب أو Aggregate، فلا تفترض وجود ضمان Per-key Partition لم توثقه Beta. وضعت Cloudflare Key-based ordering ضمن Roadmap، وهذا يعني أن التصميم لا يجب أن يتصرف كأنها متاحة اليوم.
حتى يصل هذا العقد، تشمل الخيارات Consumer واحدة للجزء المرتب، أو Serialization لاحقة حسب Aggregate Key، أو Version Checks ترفض الانتقالات القديمة، أو Domain Model تكون أحداثه Commutative. يضحي كل خيار إما بالـThroughput أو البساطة أو Latency. اختر داخل معمارية Consumer ولا تخفِ القرار خلف كلمة «Stream».
تقدم Subscriptions المستقلة فائدة واضحة، لكنها تضاعف العمل. تستطيع Analytics وFraud Detection وSearch Indexing تتبع مواضع مستقلة وإعادة تشغيل التاريخ، لكن كل واحدة تحتاج Capacity وMonitoring وتوقعات Retention ومعالجة فشل خاصة بها.
صمّم عقد الحدث قبل وسيلة النقل
يجب أن يكون أول Schema عبارة عن Envelope، لا نسخة غير مؤرشفة من صف قاعدة البيانات. أضف event_id وevent_type وschema_version وaggregate_id وoccurred_at وdata محددة النوع. وقرر قبل الإدخال هل يسمح ببيانات شخصية أو منظمة داخل سجل يحتفظ بالأحداث.
يجب أن تدعم Consumers الإصدار الحالي والسابق من Schema أثناء Migration. التغييرات الإضافية أسهل من تغيير المعنى. وعندما يجب تغيير Semantics، انشر Event Type أو Version جديدة وشغّل Consumers القديمة والجديدة بالتوازي حتى تثبت Reconciliation صحة Projection الجديدة.
سجّل Business Timestamp من Producer بصورة منفصلة عن Server Receive Timestamp في K2. يفيد وقت الاستقبال في قياس Ingestion Delay، لكنه لا يستبدل وقت حدوث Business Event. تحقق من افتراضات الساعة قبل استخدام أي منهما للترتيب.
لا تجعل Retention سياسة Governance عرضية. تسمح حدود Beta المنشورة بمدة من ساعة إلى 30 يومًا، مع إمكانية طلب مدد أطول. اختر أقصر مدة تغطي التعافي وReplay والتدقيق. Durable Log ليست بالضرورة System of Record.
تعامل مع حدود Beta كمدخلات للمعمارية
تشمل الحدود المنشورة حاليًا 20 Streams للحساب، و100 Subscriptions لكل Stream، و5 MB لطلب Produce، ونحو 1 MB للـRecord، و10 MB لرد Consume، و10,000 Record لطلب Consume. ويسرد إعلان الإطلاق Throughput يصل إلى 30 MB/s لكل Stream و10 GB تخزين للحساب أثناء Beta.
قد تتغير هذه الحدود، لكن تصميم اليوم يجب أن يحترمها. قسّم Streams حسب دورة الحياة وحدود الأمان ومتطلبات Retention، لا حسب كل Event Type. كثرة Streams تستهلك حد الحساب وتعقد Replay. لكن Stream واحدة لكل شيء تربط الصلاحيات والـNoisy Producers وسياسات الاحتفاظ المختلفة.
نفّذ Load Test بأحجام Records وسلوك Consumers واقعيين. قِس Producer p50 وp95 وp99، وكفاءة امتلاء Batch، وEnd-to-end freshness، وتمديد Leases، والتكرار، وThroughput الوجهة، وزمن التعافي بعد تعطل Consumer. تذكر Roadmap طبقة أقل Latency، وKey ordering، وPush-based Workers، وتوافق Kafka Clients، لكن عناصر Roadmap ليست ضمانات حالية.
خطة تقييم آمنة
ابدأ بـWorkload Fan-out غير حرجة مثل Product Analytics أو Projections مشتقة من Audit. أبقِ المسار الحالي Source of Truth. نفّذ Dual-publish مع event_id ثابت، واستهلك K2 إلى Shadow Destination، ثم صالح الأعداد وافتراضات الترتيب والتكرارات مع Pipeline الحالية.
اختبر الفشل عمدًا. افقد رد Producer ثم أعد المحاولة. أوقف Consumer بعد تثبيت Transaction وقبل Ack. دع Lease تنتهي. اعزل Record مشوهًا. أوقف Consumers مدة تكفي لتراكم Backlog، ثم قِس التعافي من دون إغراق Sink.
حدد Exit Criteria قبل توسيع النطاق: Freshness Percentiles مقبولة، وعدم وجود فقد غير مفسر، ومعدل تكرار محدود، وIdempotency مثبتة، وReplay مجربة، وكلفة مضبوطة، ومالك تشغيلي. وحدد Rollback أيضًا: أوقف الإنتاج الجديد، واحتفظ بالـOffsets، واستمر بالمسار القديم حتى تنتهي Reconciliation.
القرار المعماري
يستحق K2 الاهتمام لأنه ينقل Durable Ordered Log إلى Object Storage ويعرضه كـServerless Primitive. قد يزيل ذلك Provisioning للـBrokers ويجعل Retained Fan-out عمليًا قرب Edge. لكنه يقدم مقايضة Latency واضحة، ويترك فرق التطبيق مسؤولة عن مقاومة التكرار وPoison Records وترتيب Domain وTransactions الوجهة.
السؤال الصحيح ليس هل يستطيع K2 استبدال Kafka داخل رسم معماري. السؤال هو هل تطابق عقوده الموثقة Workload: إنتاج موجه للدفعات، وضمان At-least-once، وPull Subscriptions مستقلة، وRetention محدودة، وحدود Beta الحالية.
إذا طابقت هذه الحدود الاحتياج، يستطيع K2 تبسيط البنية المحيطة بتاريخ الأحداث. أما إذا احتاجت Workload اليوم إلى Tail Latency تحت الثانية، أو توافق Kafka ناضج، أو Strict Per-key Ordering، أو تحكم Workflow على مستوى الرسالة، فإن وثائق الإطلاق نفسها تقدم أسبابًا للانتظار أو اختيار Primitive أخرى.
المراجع الرسمية
تدعم هذه المراجع سلوك الأدوات المذكورة. الأمثلة وقرارات التصميم توضيحية، ويجب تكييفها مع متطلبات المشروع وإصداراته.
إعداد: Noor Yasser
تعمل على تحدٍ تقني مشابه؟
أساعد الفرق على تحويل القرار المعماري إلى نطاق واضح وتنفيذ يمكن تشغيله ومراجعته بثقة.




