GuilhermeCoollink Ответов: 3

Ошибка при взаимодействии WCF с другим WCF


У меня есть 2 Службы Windows. Каждая служба Windows хостинг WCF сервиса.

ControllerService хосты ControllerWCF
CalcService хосты CalcWCF

В ControllerWCF есть несколько методов, которые пойдут в сторону CalcWCF для обработки некоторых данных. Затем у меня есть третье консольное приложение для тестирования моих сервисов.

Используя третье консольное приложение, чтобы проверить его, я создал 3 соединения.
1-й идет непосредственно к ControllerWCF, который выполняет метод в ControllerWCF
2-й идет непосредственно к CalcWCF, который выполняет метод в CalcWCF
3-й идет непосредственно к ControllerWCF, который выполнит метод в CalcWCF (тот же метод, что и 2-е соединение)

При запуске приложения 1-е и 2-е соединения будут выполняться безупречно. При переходе к 3-му соединению он выйдет из строя и вернет это сообщение об исключении:


An existing connection was forcibly closed by the remote host

System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted()
System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs)
System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs e)
System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncFailure(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)


Также появилось это сообщение об ошибке в средстве просмотра трассировки службы
The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'.


-		$exception	{"The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:57.2419783'."}	System.ServiceModel.CommunicationException


SocketException: An existing connection was forcibly closed by the remote host


Соединение с розеткой было прервано. Это может быть вызвано ошибкой обработки Вашего сообщения, превышением тайм-аута приема удаленным хостом или основной проблемой с сетевыми ресурсами. Местные таймаут на сокете '00:00:59.9989991'.

Что я уже пробовал:

Я активировал трассировку службы, увеличил время ожидания, maxItemsInObjectGraph и т. д.

Я до сих пор не знаю, как решить эту проблему. Скоро я вставлю свой файл app. config из всех служб WCF.

F-ES Sitecore

Проверьте, что в конфигурации ControllerWCF есть правильные данные для службы CalcWCF, то есть правильный uri\host\port и т. д. Возможно, добавьте некоторое ведение журнала в ControllerWCF, чтобы точно записать, какие URI он собирается вызвать.

GuilhermeCoollink

Когда CalcService запускается и размещает CalcWCF, Uri CalcWCF хранится в базе данных. ControllerWCF использует ControllerService, чтобы получить URI для CalcWCF. Я начал печатать материал на консоль, чтобы убедиться, что он извлекает правильный Uri, и там все гладко :/

F-ES Sitecore

Попробуйте проследить за скрипачом, чтобы узнать, может ли это дать вам больше информации.

GuilhermeCoollink

Попробую проследить за скрипачом. На этом экране отображаются выходные данные, поступающие из обеих служб, а также из консоли тестирования http://imgur.com/ll97JBe

GuilhermeCoollink

Просто заметил, что он не работает с net.tcp только с http. Скрипач тогда никуда не годится :x

3 Ответов

Рейтинг:
23

GuilhermeCoollink

Хорошо, я нашел проблему... Я использовал пользовательский ChannelWrapper, который уже был построен от предыдущего разработчика, и я изменил способ общения с помощью "традиционного" ChannelFactory из MSDN


using (ChannelFactory<IWCFCommonService> channelFactory2 = new ChannelFactory<IWCFCommonService>(new NetTcpBinding()))
                {
                    IWCFCommonService channel2 = channelFactory2.CreateChannel(new EndpointAddress("net.tcp://127.0.0.1:8991/CLCalcWCF/Service"));
                    channel2.CallTestCalc();
                }


Это позволило мне работать без каких-либо проблем. Не обращай внимания на этот вопрос... была "унаследованная" проблема кода <.<


Рейтинг:
0

Thomas Nielsen - getCore

Если это займет много времени, и, возможно, вашего 60-секундного дефолта будет недостаточно. Попробуйте открыть время передачи:
Настройка значений времени ожидания на обязательное | Майкрософт документы[^]

Если проблема заключается не в таймауте, а в ошибке, убедитесь, что вы ловите все ошибки в своем методе на службе и возвращаете ошибки, если вы будете обертываться в FaultException

Как обернуть управляемые исключения в FaultException[^]

Вы не хотите рисковать тем, что ваш канал связи умрет из-за необработанных исключений, так как вы не заметите этого до следующего звонка.


Рейтинг:
0

Bernhard Hiller

Самое главное, чтобы проверить с таким сообщением об ошибке, действительно ли это проблема тайм-аута: вы получите это вводящее в заблуждение сообщение, даже если ошибка произойдет немедленно.

Типичной причиной проблем являются типы, которые не известны службе WCF (или имеют разные версии на разных машинах).

Также посмотрите на размеры объектов / строк / массивов, которые могут передаваться между сервисами.

В качестве простого шага для анализа я бы заменил проблемный вызов между службами простым методом, использующим общие типы. Иногда я интегрирую метод string Foo() для таких целей в моих сервисах: если это работает, то базовая конфигурация WCF, брандмауэр и тому подобные вещи в порядке.


GuilhermeCoollink

Я только что создал демо-приложение, чтобы попробовать его, вот что я придумал:

https://github.com/GuilhermeGomesCL/WCF_Calling_WCF/tree/master/WCF_Calling_WCF

Вот, это прекрасно работает. Я могу позвонить в WCF из другого WCF. Я реализую точно такой же способ в своем другом приложении... но все равно выдает ошибку, и я создал простой метод, который ничего не возвращает. Все они пусты и все равно я получаю одну и ту же ошибку сокета