Сбой веб-службы WCF при получении больших данных
Я вызываю веб-службу WCF локально (или удаленно), которая отлично работает с небольшими объемами данных (около 25 строк < 1K данных и т. Д.). Но когда данные становятся больше (около 300 строк), веб-служба перестает работать. Ниже приведены исключение, внутреннее исключение и трассировка стека из внутреннего исключения.
Служба также, кажется, занимает необычно много времени, чтобы выполнить локально (я добавляю это, потому что это может дать вам некоторую подсказку в решении). Получение большого объема данных занимает 3 секунды на стороне сервера, а небольшое количество данных - 1 секунды на стороне сервера. Однако запуск веб-службы (локально) для возврата небольшого объема данных занимает 24 секунды.
Я также включил информацию о привязке из app.config из моего клиентского тестового приложения.
========= СВЯЗАННАЯ ИНФОРМАЦИЯ ===========
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFormsService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="02:00:00" sendTimeout="00:02:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="1000000000"
maxArrayLength="1000000000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None"
proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://monica-pc/TrialIQSvc/FormsService.svc/FormsService/FormsService.Svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IFormsService"
contract="WebService.IFormsService" name="BasicHttpBinding_IFormsService" />
</client>
========= ИСКЛЮЧИТЕЛЬНЫЕ ДАННЫЕ =============
**Exception**: An error occurred while receiving the HTTP response to http://monica-pc/TrialIQSvc/FormsService.svc/FormsService/FormsService.Svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
**Inner Exception**: The underlying connection was closed: An unexpected error occurred on a receive.
**Stack trace**:
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at Test.WebService.IFormsService.GetFormGroupInstance(String formGroupId, String subjectId, String userId)
at Test.WebService.FormsServiceClient.GetFormGroupInstance(String formGroupId, String subjectId, String userId) in G:\SVNTrialIQ\trunk\Common\trunk\source\Forms\Test\Service References\WebService\Reference.cs:line 59
at Test.Form1.btnInstanceInfo_Click(Object sender, EventArgs e) in G:\SVNTrialIQ\trunk\Common\trunk\source\Forms\Test\Form1.cs:line 408
5 ответов
Есть много вещей, которые могут пойти не так.
Прежде всего, как уже предложил "дарин" - попробуйте включить трассировку сообщений и посмотрите, что это дает.
Второе - вы можете столкнуться с таймаутом. Вы сказали, что для возврата вашего небольшого набора данных понадобилось около 24 секунд, ваш большой набор данных в 12 раз больше (300 против 25 строк), так что это может занять 288 секунд - но ваш sendTimeout
установлен на 2 минуты - так что это может быть причиной. Попробуйте увеличить этот параметр, скажем, до 10 минут - этого должно быть достаточно:
<binding name="BasicHttpBinding_IFormsService"
sendTimeout="00:10:00"
Если это не решает проблему - вы можете попытаться использовать потоковую передачу для возврата больших объемов данных:
<binding name="BasicHttpBinding_IFormsService"
transferMode="StreamedResponse">
Пока только ваши ответы являются большими, это должно работать. Конечно, вам придется реструктурировать своего клиента, немного вызвав сервис для обработки потоковой передачи (создайте метод контракта = сервис, который возвращает Stream
как его возвращаемое значение, и используйте поток для чтения данных порциями с сервера). Если это обычный сценарий для вас, это может сработать и стоить затраченных усилий (и это позволит вам снова уменьшить размер буфера, чтобы избежать атаки типа "отказ в обслуживании" из-за огромных сообщений).
См. Большое введение в потоковую передачу сообщений WCF для получения дополнительной информации о потоковой передаче.
А если ничего не поможет - вернись и дай нам знать!
Марк
Чтобы получить расширенную информацию об ошибках, попробуйте использовать SvcTraceViewer.
Попробуйте это: в разделе system.web. Установите атрибут maxRequestLength.
<httpRuntime executionTimeout="90" maxRequestLength="1048576" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100"/>
Эта ошибка может быть из-за несоответствия контракта. Рассмотрим трехслойное приложение ниже...
UI Layer
|
Process Layer
|
Data Access Layer
-> Contract Between Process and UI layer has the same enum with missing (Onhold = 3). Enum: Start = 1, Stop = 2.
-> Contract Between Data Access And Process layer has enum Enum: Start = 1,Stop = 2,Onhold = 3.
В этом случае мы получим ту же ошибку в ответе уровня процесса.
Такая же ошибка возникает при другом несоответствии контракта в многослойном приложении.
Возможно, вам не хватает какой-либо конфигурации на стороне сервера