سؤال

لدينا تطبيق يحتوي على خدمة WCF (* .svc) قيد التشغيل على IIS7 والعملاء المختلفة الذين يعانون من الخدمة. الخادم قيد التشغيل خادم WIN 2008. يعمل العملاء إما خادم Windows 2008 أو Windows 2003 Server. أحصل على الاستثناء التالي، الذي رأيته في الواقع يرتبط بعدد كبير من مشكلات WCF المحتملة.

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. 

لقد زادت المهلة إلى 30 دقيقة ولم يحدث الخطأ. هذا يخبرني أن هناك شيئا آخر في اللعب، لأن كمية البيانات لا يمكن أن تأخذ 30 دقيقة لتحميل أو تنزيلها.

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

 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

على الخادم: لقد حاولت (وحدي حاليا) إعدادات الربط التالية:

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

يبدو أن له تأثير.

لقد حاولت (وحياتها حاليا) إعدادات الاختناق التالية:

<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

يبدو أن له تأثير.

لدي حاليا الإعدادات التالية لخدمة WCF.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

ركض مع ConcurrencyMode.Multiple لفترة من الوقت، ولم يحدث الخطأ.

لقد حاولت إعادة تشغيل IIS، وإعادة تشغيل خادم SQL الأساسي، وإعادة تشغيل الجهاز. كل هذه لا يبدو أن يكون لها تأثير.

لقد حاولت تعطيل جدار حماية Windows. يبدو أن له تأثير.

على العميل، لدي هذه الإعدادات:

maxReceivedMessageSize="2147483647"

<system.net>
    <connectionManagement>
    <add address="*" maxconnection="16"/>
</connectionManagement> 
</system.net>

عميلي يغلق اتصالاته:

var client = new MyClient();

try
{
    return client.GetConfigurationOptions();
}
finally
{
    client.Close();
}

لقد غيرت إعدادات التسجيل للسماح بالاتصالات الصادرة:

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

لقد جربت الآن مؤخرا SvctReAceViewer.exe. تمكنت من التقاط استثناء واحد على نهاية العميل. أرى أن مدةها دقيقة واحدة. بالنظر إلى تتبع جانب الخادم، أستطيع أن أرى أن الخادم ليس على علم بهذا الاستثناء. الحد الأقصى للمدة التي يمكنني رؤيتها هي 10 ثوان.

لقد بحثت في اتصالات قاعدة البيانات النشطة باستخدام exec sp_who على الخادم. ليس لدي سوى عدد قليل (2-3). لقد نظرت إلى اتصالات TCP من عميل واحد باستخدام TCPView. عادة ما تكون حوالي 2-3 وشهدت ما يصل إلى 5 أو 6.

ببساطة، أنا مرت. لقد جربت كل ما يمكن أن أجده، ويجب أن أفتقد شيئا بسيطا للغاية أن يكون خبير WCF قادرا على رؤيته. إنه شعور قناعي أن هناك شيئا ما يحظر عملائي على المستوى المنخفض (TCP)، قبل أن يتلقى الخادم في الواقع الرسالة و / أو أن هناك شيء في انتظار الرسائل على مستوى الخادم وعدم السماح لهما بأي مطلقا.

إذا كان لديك أي عدادات أداء يجب أن أنظر إليها، فيرجى إخبارنا بذلك. (يرجى الإشارة إلى القيم السيئة، لأن بعض هذه العدادات يصعب فك التشفير). أيضا، كيف يمكنني تسجيل حجم رسالة WCF؟ أخيرا، هل هناك أي أدوات لدينا من شأنها أن تسمح لي باختبار عدد الاتصالات التي يمكنني تحديدها بين موكلي والخادم (بشكل مستقل عن طلبي)

شكرا على وقتك!

وأضاف معلومات اضافية 20 يونيو:

تطبيق WCF الخاص بي يفعل شيئا مشابها لما يلي.

while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

باستخدام Wireshark، رأيت أنه عند حدوث الخطأ، لدي إعادة إرسال خمسة TCP متبوعا بإعادة تعيين TCP لاحقا. تخميني هو RST قادما من WCF مما يؤدي إلى مقتل الاتصال. تقرير الاستثناء الذي أحصل عليه هو من توقيت Step3.

اكتشفت ذلك من خلال النظر إلى TCP Stream "TCP.Stream EQ 192". ثم قمت بتوسيع مرشحي إلى "TCP.Stream EQ 192 و HTTP و HTTP.REQUEST.METHOD EQ Post" ورأى 6 وظيفة أثناء هذا الدفق. يبدو أن هذا غريب، لذلك قمت بفحص دفق آخر مثل TCP.Stream EQ 100. كان لي ثلاث وظائف، والتي تبدو أكثر طبيعية بعض الشيء لأنني أفعل ثلاث مكالمات. ومع ذلك، أقوم بإغلاق اتصالي بعد كل مكالمة WCF، لذلك كنت أتوقع مكالمة واحدة لكل دفق (لكنني لا أعرف الكثير عن TCP).

التحقيق أكثر قليلا، قمت بإلقاء تحميل حزمة HTTP على القرص لإلقاء نظرة على ما هذه المكالمات الستة حيث.

1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

تخميني هو عملاء متزامنان يستخدمان نفس الاتصال، ولهذا السبب رأيت التكرارات. ومع ذلك، لا يزال لدي الكثير من المشكلات التي لا أستطيع فهمها:

أ) لماذا تالف الحزمة؟ شبكة عشوائية فلوك - ربما؟ الحمل gzpeced باستخدام رمز العينة هذا: http://msdn.microsoft.com/en-us/library/ms751458.aspx. - هل يمكن أن يكون الكود عربات التي تجرها الدواب مرة واحدة في حين أن تستخدم في وقت واحد؟ يجب أن اختبار دون مكتبة gzip.

ب) لماذا أرى الخطوة 1 والخطوة 2 قيد التشغيل بعد انتهاء انتهت مهلة العملية التالفة؟ يبدو لي كما لو كان لا ينبغي أن تحدث هذه العمليات. ربما أنا لا أنظر إلى الدفق الصحيح لأن فهمي ل TCP معيبة. لدي تدفقات أخرى تحدث في نفس الوقت. يجب علي التحقيق في تيارات أخرى - إظهار نظرة سريعة على الجداول 190-194 أن وظيفة Step3 تحتوي على بيانات حمولة مناسبة (غير تالفة). دفعني إلى إلقاء نظرة على مكتبة Gzip مرة أخرى.

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم عميل .NET، فلا قد لا تحدد

//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

هنا هو السؤال الأصلي والإجابة خدمة WCF اختناق

تحديث:

قد يبدأ هذا التكوين في تطبيق عميل .NET قيد التشغيل أو كلما قبل بدء الاختبارات الخاصة بك.

علاوة على ذلك، يمكنك الحصول عليها في ملف App.config بالإضافة إلى ذلك

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>

نصائح أخرى

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

إذا أظهرت هذه تلك العمليات، فستكون خطوتي التالية هي الذهاب إلى مستوى أقل، وإلقاء نظرة على طبقة النقل الفعلية.

يمكن أن تكون WireShark أو أداة التقاط حزمة مماثلة أخرى مفيدة للغاية في هذه المرحلة. أفترض أن هذا يعمل عبر HTTP على المنفذ القياسي 80.

تشغيل Wireshark على العميل. في الخيارات عند بدء التقاط، اضبط مرشح الالتقاط tcp http and host service.example.com - هذا سوف يقلل من كمية حركة المرور غير ذات الصلة.

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

عند ظهور خطأ، يمكنك إجراء شبك الجر خلال سجلات Wireshark للعثور على بداية المكالمة. انقر بزر الماوس الأيمن فوق الحزمة الأولى التي يتم الاتصال بها عميلك (يجب أن تكون شيئا مثل الحصول على /service.svc أو نشر /service.svc) وحدد متابعة تيار TCP.

سيقوم Wireshark بفك تشفير محادثة HTTP بأكملها، حتى تتمكن من التأكد من أن WCF يقوم بالفعل بإرسال ردود الظهر.

من عند: http://www.codeProject.com/kb/wcf/wcf_operation_timeout_.aspx.

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

أواجه مشكلة مماثلة للغاية. في الماضي، هذا مرتبط بمشاكل التسلسل. إذا كنت لا تزال تواجه هذه المشكلة، فيمكنك التحقق من أنه يمكنك تسلسل الكائنات التي تعودها بشكل صحيح. على وجه التحديد، إذا كنت تستخدم كائنات LinQ-To-SQL التي لها علاقات، فهناك مشكلات تسلسل معروفة إذا وضعت مرجعا مرة أخرى على كائن طفل إلى الكائن الأصل وتحديد المرجع المرجعي كدولة بيانات.

يمكنك التحقق من التسلسل عن طريق كتابة تطبيق Console يسقط الكائنات الخاصة بك وتغمره باستخدام DataConctractSerializer على جانب الخادم وأي طريقة تسلسل يستخدم عميلك. على سبيل المثال، في تطبيقنا الحالي، لدينا كل من عملاء WPF ومدمج. كتبت تطبيق وحدة التحكم للتحقق من أنه يمكنني تسلسل باستخدام DataConctractSerializer والتحيز باستخدام XMLDesserializer. قد تحاول ذلك.

أيضا، إذا كنت تقوم بإرجاع كائنات LinQ-To-SQL التي تحتوي على مجموعات أطفال، فقد تحاول التأكد من تحميلها بفارغ الصبر على جانب الخادم. في بعض الأحيان، بسبب التحميل الكسول، لا يتم ملء الكائنات التي يتم إرجاعها وقد تتسبب في أن السلوك الذي تراه حيث يتم إرسال الطلب إلى طريقة الخدمة عدة مرات.

إذا كنت قد حل هذه المشكلة، فأنا أحب أن أسمع كيف أنا عالق معها أيضا. لقد تحققت من أن مشكلتي ليست تسلسل لذلك أنا في حيرة.

تحديث: لست متأكدا مما إذا كان سيساعدك أي أداة "عارض خدمة تتبع الخدمة" فقط حل مشكلتي بعد 5 أيام من تجربة مشابهة للغاية لك. من خلال إعداد تتبع ثم النظر إلى XML RAW، وجدت الاستثناءات التي كانت تسبب مشاكل التسلسل الخاصة بي. كانت مرتبطة بأكائن LinQ-To-SQL التي كانت في بعض الأحيان المزيد من الأشياء الأطفال أكثر مما يمكن تسلسله بنجاح. يجب أن تمكين إضافة ما يلي إلى ملف Web.config الخاص بك:

<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
  </sources>

يمكن فتح الملف الناتج باستخدام أداة عارض Trace الخدمة أو فقط في IE لفحص النتائج.

هل تغلق الاتصال بخدمة WCF بين الطلبات؟ إذا لم تفعل ذلك، فسترى هذا المهلة الدقيقة (في النهاية).

لقد قمت فقط بحل المشكلة. لقد وجدت أن العقد في ملف app.config قد قمت بتكوين خطأ.

<client>
<endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*">
</endpoint>
</client>

<bindings>
    <wsHttpBinding>
        <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <**security mode="None">**
                <transport clientCredentialType="None"></transport>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

تأكيد التكوين الخاص بك في العقدة <security>، قيمة "الوضع" السمة "لا شيء". إذا كانت القيمة الخاصة بك هي "النقل"، يحدث الخطأ.

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

هل تحقق من آثار WCF؟ WCF لديه ميل إلى ابتلاع الاستثناءات وإرجاع الاستثناء الأخير فقط، وهو المهلة التي تحصل عليها، لأن نقطة النهاية لم تعد أي شيء مفيد.

سوف تتلقى أيضا هذا الخطأ إذا قمت بتمرير كائن مرة أخرى إلى العميل الذي يحتوي على خاصية من النوع Enum الذي لم يتم تعيينه بشكل افتراضي ولن يكون هذا ENUM قيمة خرائط إلى 0. أي enum MyEnum{ a=1, b=2};

يبدو أن هذه الرسالة الاستثناء عامة للغاية ويمكن استلامها بسبب مجموعة متنوعة من الأسباب. هربنا هذا أثناء نشر العميل على أجهزة Windows 8.1. يعمل عميل WCF الخاص بنا داخل خدمة Windows واستطلاعا باستمرار خدمة WCF. تعمل خدمة Windows ضمن مستخدم غير مسؤول. تم إصلاح المشكلة عن طريق تعيين العميل ClientCredentyPype إلى "Windows" في تكوين WCF للسماح للمصادقة بالمرور، كما في ما يلي:

      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>

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

لا ينبغي أن تكون اتصال متعددة قادمة من آلات مختلفة / IP مشكلة ومع ذلك.

هناك مزيد من المعلومات في هذه الرسالة MSDN:

http://msdn.microsoft.com/en-us/library/bb463275.aspx.

تحقق من sproperty maxconcurrents.

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