محتويات الدورة

Go / المتقدم: السلامة والأداء وتصميم الخدمات / الدرس 14

الإلغاء وخطوط المعالجة المحدودة

ابن خطوط عاملين ذات حدود صريحة للصفوف والروتينات والإلغاء ومسؤوليات الإغلاق.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • تعيين مسؤول التوقف والانتظار لكل مرحلة.
  • جعل الإرسال والاستقبال واعيين بالإلغاء.
  • تحديد عدد العاملين وحفظ سياسة الخطأ والاعتماد.

كل مرحلة تملك عمرا

يربط خط المعالجة مراحل تحول أو تنقل قيما. حدد من يبدأ كل مرحلة ويغلق خرجها وما يحدث بعد رفض التابع ومن ينتظر الجميع. المرحلة التي قد تحجب للأبد بعد خروج المستهلك ناقصة ولو صح خرج النجاح.

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

الإرسال المهجور يحتاج مسار خروج

يبدأ المثال الأول منتجا غير مخزن بسياق ملغى مسبقا. تنتظر main الاكتمال قبل الاستقبال، فلا يجهز الإرسال ويجب أن ينهي فرع الإلغاء العامل. يغلق العامل الخرج ثم يشير done. لا يلزم ادعاء توقيت ولا اختيار بين حالتين جاهزتين.

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

go منتج ملغى بانتظار صريح
package main

import (
	"context"
	"fmt"
)

func produce(ctx context.Context) (<-chan int, <-chan struct{}) {
	output := make(chan int)
	done := make(chan struct{})
	go func() {
		defer close(done)
		defer close(output)
		select {
		case output <- 7:
		case <-ctx.Done():
			return
		}
	}()
	return output, done
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	output, done := produce(ctx)
	<-done
	_, ok := <-output
	fmt.Println("closed without value", !ok)
}
الناتج المتوقع
closed without value true

لا يتاح مستقبل قبل done، فينهي الإلغاء المنتج ويغلق الخرج.

تنسيق الإغلاق بعد كل مرسل

للبرنامج التالي عاملان وقناة وظائف غير مخزنة وقناة نتائج. يملك المنتج إغلاق الوظائف ويغلق منسق النتائج بعد العاملين فقط. يستنزف الجامع النتائج ويجمع المربعات؛ تغير الجدولة الترتيب لا المجموع. تمنع الإرسالات الواعية بالسياق بقاء العاملين عند هجر المستهلك والإلغاء.

لكل روتين طريق اكتمال. تحدث إضافات WaitGroup قبل الإطلاق ويؤجل كل عامل Done. يجب في الإنتاج انتظار المنتج والمنسق حسب الملكية عند العودة المبكرة؛ ويثبت الاستنزاف الناجح هنا تقدمهما المطلوب دون نوم.

go خط محدود بعاملين
package main

import (
	"context"
	"fmt"
	"sync"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	jobs := make(chan int)
	results := make(chan int)
	producerDone := make(chan struct{})
	go func() {
		defer close(producerDone)
		defer close(jobs)
		for n := 1; n <= 4; n++ {
			select {
			case jobs <- n:
			case <-ctx.Done():
				return
			}
		}
	}()
	var workers sync.WaitGroup
	workers.Add(2)
	for i := 0; i < 2; i++ {
		go func() {
			defer workers.Done()
			for n := range jobs {
				select {
				case results <- n * n:
				case <-ctx.Done():
					return
				}
			}
		}()
	}
	coordinatorDone := make(chan struct{})
	go func() { defer close(coordinatorDone); workers.Wait(); close(results) }()
	total := 0
	for result := range results {
		total += result
	}
	<-producerDone
	<-coordinatorDone
	fmt.Println("squares", total)
}
الناتج المتوقع
squares 30

تجمع المربعات الأربعة إلى ثلاثين وتُلاحظ أعمار المنتج والعاملين والمنسق.

تحديد الخطأ الأول والنجاح الجزئي

تحتاج العملية المتزامنة سياسة خطأ: التوقف عند أول مبلغ أو الجمع أو متابعة المستقل. يوقف الإلغاء غير اللازم ويبقى انتظار كل مطلق على المالك. إذا اعتُمدت آثار فلا يوحي الخطأ بأن شيئا لم يحدث؛ وثق النتائج الجزئية وحدود المعاملة.

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

اختبار الإنهاء كعملية عادية

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

لا تغلق قناة مشتركة من معالجات إلغاء عشوائية مع مرسلين نشطين. ليغلق المالك بعد انتهاء الإرسال أو استخدم السياق دون إغلاقها. لا تستبدل المخازن وrecover بروتوكول الملكية. راجع ترتيب التنظيف والمراجع المحفوظة عند كل عودة مبكرة.

الأخطاء الشائعة وإصلاحها

يعود التابع مبكرا ولا ينتهي السابق.

لماذا يحدث؟
يفتقر إرسال للإلغاء أو يغيب مالك الانتظار.
كيف تصلحه؟
أضف اتصالا واعيا بالإلغاء وانتظر المراحل.
كيف تتجنب تكراره؟
اختبر رفض المستهلك المبكر.

يسبب الإلغاء هلع إرسال لمغلقة.

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

يستهلك عدد عاملين ثابت ذاكرة بلا حد.

لماذا يحدث؟
القبول أو تخزين النتائج غير محدود.
كيف تصلحه؟
حد الصف وحدد الحمل الزائد.
كيف تتجنب تكراره؟
قس العمل المنتظر والنشط.

اختبر فهمك

1. يحتاج المستدعي أول نتيجة ناجحة فقط. ماذا يفعل قبل العودة إذا ملك الجميع؟

اعرض الحل المشروح

يشير بالإلغاء ويضمن ملاحظته في كل حجب وينتظر الروتينات قبل تحرير المشترك أو العودة. يحفظ النتيجة وفق ملكيتها. لا يكتف بالتوقف عن القراءة فقد يحجب العاملين للأبد. ويشخص فشل الانتظار المحدود كعيب عمر لا يخفيه بتسريبهم.

2. لماذا لا يثبت مخزن نتائج من ألف غياب التسرب؟

اعرض الحل المشروح

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

أهم ما تعلمته

  • حد القبول والصفوف والعاملين والإنهاء معا.
  • ألغ العمل غير اللازم وانتظر كل روتين مملوك.
  • يحتاج الإغلاق والخطأ والإعادة واعتماد الآثار قواعد صريحة مستقلة.

المراجع الرسمية