سؤال

لديّ محرك استضافة WCF صغير أكتبه من شأنه أن ينشئ ديناميكيًا على أساس ملف .Config. تتمثل الفكرة العامة في السماح لنا بإزالة الخدمات الحالية ، وكذلك إضافة خدمات جديدة ، في وقت التشغيل دون الحاجة إلى جلب جميع خدماتنا في وضع عدم الاتصال.

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

System.InvalidOperationException: The ChannelDispatcher at 'net.pipe://localhost/' with contract(s) '"ITestService"' is unable to open its IChannelListener. --->
System.InvalidOperationException: A registration already exists for URI 'net.pipe://localhost/'.

أنا في الواقع أواجه الخطأ أثناء اختبار الوحدة. سوف تمارس الاختبارات وحدة واحدة ، والتي تغلق بالكامل من خدمة Servicehosts واستضافة المحرك قدر الإمكان من الناحية الإنسانية. ثم يقوم بإنشاء مثيل آخر لمحرك الاستضافة ، والذي يحاول إعادة إنشاء نفس الخدمات مرة أخرى لاختبار مختلف. يواجه الاختبار الثاني الخطأ أعلاه. أظن أنه بينما تم استدعاء ServiceHost.close () ، فإن هذا لا يدمر مضيف الخدمة ... لذلك لا يزال يتسكع في الذاكرة. لا يمكنني معرفة ما إذا كانت GC تقوم بتنظيف مضيفي الخدمة القديمة أم لا ... تستمر المشكلة دون أن تنفصل بعد حدوثها في البداية (كما تمكنت من تحديد ... لقد انتظرت حوالي 30 دقيقة حتى الآن. )

ملف التكوين الخاص بي لـ System.ServicEmodel كما يلي:

  <system.serviceModel>
    <services>
      <service name="Campus.Core.ServiceModel.TestServiceStub">
        <endpoint          
          address="net.pipe://localhost"          
          binding="netNamedPipeBinding"           
          contract="Campus.Core.ServiceModel.ITestService"
        />
      </service>
    </services>
  </system.serviceModel>
هل كانت مفيدة؟

المحلول

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

1) أثناء اختبار الوحدة ، إذا تم مواجهة استثناء ، فعادة ما ينفجر من الكود الذي يتم اختباره قبل إغلاق Servicehost. ترك هذا servicehost ملزمة بنقطة نهاية معينة. تسبب هذا في فشل جميع الاختبارات اللاحقة التي مارست نفس قطعة الكود. بينما كنت أقوم بعمل BDD مع Subspec و Xunit ، قامت حالة اختبار واحدة (بالقلق في شروط BDD) التي أجرت اختبارًا واحدًا لكل اختبار ، ويمكن أن تشمل حالة اختبار واحدة ما يصل إلى عشرات أو أكثر من التأكيدات.

2) حذار من نقطة نهاية MEX. يمكن أن توجد نقطة نهاية MEX مرة واحدة فقط لكل خدمة. في البداية ، قمت بإنشاء نقطة نهاية HTTP و Net.TCP MEX. هذا تسبب في مشكلة ، ومع ذلك ، فإن أي حالة من نقطة نهاية MEX بدأت في المرتبة الثانية ألقى استثناء. بشكل عام ، إذا كنت تستخدم نقطة نهاية MEX ، فإن HTTP هو البروتوكول الأكثر فائدة لاستخدامه ، ما لم تكن هناك مشكلة في البنية التحتية المادية التي تمنعك من القيام بذلك.

بشكل عام ، فإن استدعاء طريقة Close () على خدمة Servicehost سيؤدي إلى إلغاء ربطها تمامًا ، مما يسمح بأي عناوين كانت مرتبطة مسبقًا بنقاط النهاية قابلة للاستخدام مرة أخرى. في بعض الأحيان قد يستغرق الإغلاق بعض الوقت ، وفي حالات نادرة ، قد يتم طرح استثناء. إذا كنت تقوم بـ BDD مع Subspec واتباع قاعدة التأكيد الفردي لكل اختبار ، فإن استثناء يتم إلقاؤه في اختبار واحد يمنع إغلاق الخدمات سيؤدي إلى فشل جميع الاختبارات اللاحقة.

نصائح أخرى

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

تستخدم عينة Idesign Inprocfactory هذا النهج ، لذلك قد تتمكن من استخدامه كما هو:

http://www.idesign.net/idesign/desktopdefault.aspx؟tabindex=5&tabid=11

لاحظ أنه سيتعين عليك التسجيل في موقع Idesign من أجل تنزيل العينة ، وسوف يرسلون لك الإعلان العرضي حول التدريب وما شابه ، لكن هذا ليس كثيرًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top