DeepSeek Harness: عزل الخدمات والنطاق

آخر تحديث: 2026-08-31

في بيئات الوكلاء المتعددين والجلسات المتعددة، الخدمات المشتركة نعمة ونقمة — الخدمات العامة مريحة لكنها عرضة للتعارض، الخدمات المعزولة آمنة لكن تكلفة الاتصال أعلى. نظام النطاق في Cordis يوازن بينهما: مشتركة افتراضياً، معزولة عند الطلب.

💡 نصيحة: المبدأ الأساسي للنطاق هو "مشتركة افتراضياً، معزولة عند الطلب" — معظم الخدمات يمكن مشاركتها عالمياً؛ فقط الخدمات التي تحتاج عزل تتطلب إعدادات isolate. عدم العزل هو القاعدة؛ العزل هو الاستثناء.

📋 المتطلبات المسبقة: أكمل 19-service.md، تفهم صنف Service الأساسي

1. ما ستتعلمه

عزل ونطاق الخدمة


2. النطاق العام

(1) السلوك الافتراضي

افتراضياً، جميع الخدمات عامة — هناك نسخة واحدة فقط عبر نسخة DSH بالكامل:

TYPESCRIPT
export default class CacheService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'cache')  // فريد عالمياً
  }
}

(2) خصائص الخدمة العامة

الخاصية الوصف
أحادية نسخة واحدة فقط لكل عملية
مشتركة جميع الجلسات والطلبات تتشارك نفس الحالة
بدون عزل البيانات المُعدّلة بالجلسة A مرئية للجلسة B

(3) السيناريوهات المُطبقة

(4) ▶ مثال 4

TYPESCRIPT
// ❌ الذاكرة المؤقتة العامة تُسبب تسرب بيانات عبر الجلسات
export default class CacheService extends Service {
  private data = new Map<string, any>()
  
  set(key: string, value: any) {
    this.data.set(key, value)
  }
}

// الجلسة A: ctx.cache.set('temp', 'secret-data')
// الجلسة B: ctx.cache.get('temp') → 'secret-data' (تسرب!)

3. نطاق الجلسة

(1) المفهوم

نطاق الجلسة يُنشئ نسخة خدمة مستقلة لكل جلسة:

TYPESCRIPT
export default class SessionCacheService extends Service {
  static scope = 'session'

  constructor(ctx: Context) {
    super(ctx, 'session-cache')
  }
}

(2) ▶ مثال 2

100%
graph LR
    S1[الجلسة A أُنشئت] --> C1[نسخة CacheService A]
    S2[الجلسة B أُنشئت] --> C2[نسخة CacheService B]
    S1 --> D1[الجلسة A دُمرت → CacheService A دُمر]
    S2 --> D2[الجلسة B دُمرت → CacheService B دُمر]

(3) تصريح النطاق

TYPESCRIPT
export default class SessionCacheService extends Service {
  static scope = 'session'
  // أو
  // static scope = Symbol('session')
}

(4) السيناريوهات المُطبقة

(5) تأثير العزل عبر الجلسات

TEXT 📖 للعرض فقط
الجلسة A:
  ctx.sessionCache.set('key', 'value-A')

الجلسة B:
  ctx.sessionCache.get('key') → undefined  (معزول)

الجلسة A:
  ctx.sessionCache.get('key') → 'value-A'  (متاح داخل الجلسة)

4. نطاق الطلب

(1) المفهوم

نطاق الطلب يُنشئ نسخة مستقلة لكل استدعاء أداة أو طلب LLM:

TYPESCRIPT
export default class RequestContextService extends Service {
  static scope = 'request'

  constructor(ctx: Context) {
    super(ctx, 'request-context')
  }
}

(2) دورة حياة نطاق الطلب

100%
graph LR
    R1[الطلب 1 يبدأ] --> S1[نسخة الخدمة 1]
    R2[الطلب 2 يبدأ] --> S2[نسخة الخدمة 2]
    R1 --> E1[الطلب 1 يكتمل → النسخة 1 تُدمّر]
    R2 --> E2[الطلب 2 يكتمل → النسخة 2 تُدمّر]

(3) السيناريوهات المُطبقة

(4) مقارنة مستويات النطاق الثلاثة

البُعد عام الجلسة الطلب
النسخ 1 1 لكل جلسة 1 لكل طلب
دورة الحياة عمر العملية عمر الجلسة عمر الطلب
مشاركة الحالة مشتركة عالمياً داخل الجلسة داخل الطلب فقط
الذاكرة منخفضة متوسطة عالية
الأفضل لـ إعدادات/تجمعات اتصال ذاكرة مؤقتة/تاريخ صلاحيات/توقيت

5. إعدادات isolate realm

(1) مفهوم Realm

Realm هو نطاق العزل في Cordis — إنشاء مساحات إضافات مستقلة داخل نفس نسخة DSH:

YAML
# cordis.yml
realms:
  agent-a:
    isolate: ['cache', 'tools']
    plugins:
      my-tool-a:
        $insert: ./plugins/tool-a
  
  agent-b:
    isolate: ['cache', 'tools']
    plugins:
      my-tool-b:
        $insert: ./plugins/tool-b

(2) حقل isolate

قائمة isolate تُحدد أي خدمات تحصل على نسخ مستقلة داخل الـ realm:

YAML
realms:
  my-realm:
    isolate:
      - cache       # خدمة cache تحصل على نسخة مستقلة
      - tools       # خدمة tools تحصل على نسخة مستقلة
      # الخدمات غير المُدرجة تبقى مشتركة عالمياً

(3) نسخ الخدمات داخل Realm

TEXT 📖 للعرض فقط
عام: llm (مشترك)
realm-a: cache (مستقل)، tools (مستقل)
realm-b: cache (مستقل)، tools (مستقل)

الإضافات في realm-a → ctx.cache = cache الخاص بـ realm-a
الإضافات في realm-b → ctx.cache = cache الخاص بـ realm-b
لا يؤثران على بعضهما

(4) حالات استخدام Realm

السيناريو الوصف
وكلاء متعددون وكلاء مختلفون لديهم مجموعات أدوات وذاكرات مؤقتة مختلفة
متعددو المستأجرين خدمات مستأجرين مختلفين معزولة mutually
الاختبار realm الاختبار لا يؤثر على realm الإنتاج
اختبار A/B realmان يستخدمان تطبيقات خدمة مختلفة

(5) التواصل عبر Realms

Realms معزولة افتراضياً لكن يمكنها التواصل عبر الخدمات العامة:

TYPESCRIPT
// خدمة عامة (غير متأثرة بـ isolate)
export default class EventBusService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'event-bus')  // ليس في قائمة isolate → مشترك عالمياً
  }

  emit(event: string, data: any) { /* ... */ }
  on(event: string, handler: Function) { /* ... */ }
}

// إضافة في realm-a
ctx.eventBus.emit('data-updated', { source: 'realm-a' })

// إضافة في realm-b
ctx.eventBus.on('data-updated', (data) => {
  ctx.logger.info(`received from ${data.source}`)
})

6. النطاق وإعدادات الوكيل المسبقة

(1) مفهوم الإعداد المسبق للوكيل

الإعداد المسبق للوكيل هو تهيئة مُعرّفة مسبقاً تشمل مجموعة الأدوات ومُعاملات النموذج وإعدادات النطاق:

YAML
presets:
  coder:
    model: deepseek-coder
    tools: [file_edit, shell, search]
    mode: standard
    
  reviewer:
    model: deepseek-chat
    tools: [file_edit, search]
    mode: minimal
    isolate: [cache]

(2) علاقة الإعداد المسبق والنطاق

كل إعداد مسبق يمكنه تحديد قائمة isolate، مُنشئاً نسخ خدمات مستقلة لذلك الوكيل:

TEXT 📖 للعرض فقط
وكيل coder:  cache مشترك، tools مستقل
وكيل reviewer: cache مستقل، tools مشترك

(3) سيناريو الوكلاء المتعددين

YAML
# cordis.yml
agents:
  coder:
    preset: coder
    isolate: [tools]
    
  reviewer:
    preset: reviewer
    isolate: [tools, cache]

(4) تعاون الوكلاء البيني

100%
graph TB
    subgraph Global
        LLM[llm Service]
        EVENT[event-bus Service]
    end
    subgraph Agent-Coder
        CT[tools Service]
        CC[cache Service]
    end
    subgraph Agent-Reviewer
        RT[tools Service]
        RC[cache Service]
    end
    CT --> LLM
    RT --> LLM
    CT --> EVENT
    RT --> EVENT

7. عزل الخدمات متعدد الوكلاء

(1) اختيار استراتيجية العزل

TEXT 📖 للعرض فقط
مشترك بالكامل:     جميع الخدمات عامة → بسيط لكن تعارضات محتملة
معزول بالكامل:   جميع الخدمات مستقلة → آمن لكن هدر موارد
عزل مختلط:  خدمات أساسية مشتركة + خدمات أعمال معزولة → نهج متوازن

العزل المختلط المُوصى به:

نوع الخدمة استراتيجية العزل السبب
llm مشترك استدعاءات API يمكن إعادة استخدامها
sessions مشترك إدارة جلسات موحدة
tools معزول كل وكيل له مجموعة أدوات مختلفة
cache معزول كل وكيل له ذاكرة مؤقتة مستقلة
fs مشترك نظام ملفات واحد فقط

(2) ▶ مثال 2

YAML
agents:
  frontend-dev:
    preset: coder
    isolate: [tools, cache]
    tools:
      - file_edit
      - shell
      - search
    config:
      cache:
        maxSize: 100
  
  backend-dev:
    preset: coder
    isolate: [tools, cache]
    tools:
      - file_edit
      - shell
      - search
      - database
    config:
      cache:
        maxSize: 200

(3) تقدير استهلاك الموارد

مستوى العزل الذاكرة CPU الاتصالات
مشترك عالمياً 1x 1x 1x
وكلاء 2 معزول ~2x ~1.5x ~2x
وكلاء 5 معزول ~5x ~3x ~5x

(4) كشف تسرب العزل

TYPESCRIPT
// مراقبة عدّاد نسخ الخدمات
ctx.on('service/created', (name, instance) => {
  ctx.logger.info(`service created: ${name}, total instances: ${countInstances(name)}`)
})

// إذا كان عدد نسخ خدمة يتجاوز عدد الوكلاء بكثير، قد يكون هناك تسرب

❓ أسئلة شائعة

س بدون التصريح بـ scope، هل الخدمة عامة افتراضياً؟
ج نعم. Service بدون static scope هي أحادية عامة افتراضياً.
س هل تُنظّف Services بنطاق جلسة عند انتهاء الجلسة؟
ج نعم. عند تدمير جلسة، تُنظّف نسخ Service تلقائياً، بما فيها الموارد المُسجّلة عبر ctx.effect.
س هل يمكن تعديل قائمة isolate لـ realm ديناميكياً؟
ج لا. إعدادات realm تُحدد عند البدء؛ التعديلات تتطلب إعادة التشغيل.
س هل يمكن لـ Service الوجود في نطاقات متعددة في نفس الوقت؟
ج لا. Service إما عام، أو بمستوى جلسة، أو بمستوى طلب. إذا احتجت مشاركة بيانات عبر النطاقات، استخدم ناقل أحداث عام.
س هل تكلفة أداء نطاق الطلب كبيرة؟
ج إنشاء وتدمير Services لكل طلب له تكلفة. استخدم نطاق الطلب فقط عند الحاجة الحقيقية؛ خلاف ذلك استخدم النطاق العام أو نطاق الجلسة.
س كيف أُصحح مشاكل النطاق؟
ج اطبع مُعرّف النسخة في مُنشئ Service: typescript constructor(ctx: Context) { super(ctx, 'cache') console.log(`cache instance created: ${this.id}, scope: ${this.scope}`) }

📖 ملخص


📝 تمارين

1. ⭐ أساسي: اكتب SessionStateService بنطاق جلسة يُحافظ على تخزين مفتاح-قيمة مستقل لكل جلسة. ابدأ جلستين وتحقق من عزل البيانات.

2. ⭐⭐ متوسط: هيّئ realm يعزل خدمات cache و tools. ادخل cache داخل وخارج realm، وتحقق أنك تحصل على نسخ مختلفة.

3. ⭐⭐⭐ تحدٍ: صمّم نظام وكلاء مزدوج: coder و reviewer. Coder لديه أدوات file_edit/shell، reviewer لديه أدوات file_edit/search فقط. كلاهما يشارك llm و sessions، لكن cache ومجموعات الأدوات معزولة بشكل مستقل. تحقق: أداة shell الخاصة بـ coder غير مرئية لـ reviewer، وذاكرتيهما المؤقتتين لا تؤثران على بعضهما.

Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%