Https маршрутизации WCF, вызывающие множественные запросы от службы, размещающей маршрутизатор - PullRequest
3 голосов
/ 17 февраля 2012

У меня есть сценарий, в котором мне нужно подключиться к защищенному внешнему мыльному веб-сервису с базовой аутентификацией.Обычно это не проблема, и это работает в моей локальной среде разработки с basicHttpBinding.Когда приложение развернуто, оно будет жить в демилитаризованной зоне и не будет иметь доступа к миру.Это создало потребность в службе маршрутизации в нашей внутренней сети, и новая функция маршрутизации в WCF 4.0 казалась хорошим кандидатом.Я получил код, работающий для вызова через http другой внешний сервис через службу маршрутизации в качестве PoC, а затем решил перейти на https.Я быстро обнаружил, что учетные данные имени пользователя из исходного вызывающего приложения не передаются службой маршрутизации, поэтому я реализовал пользовательский IEndpointBehavior для добавления надлежащих учетных данных к вызовам службы маршрутизации для внешнего клиента.Вот мои привязки для моего клиентского приложения, а также для моей службы маршрутизации.

Клиентское приложение:

<basicHttpBinding>
    <binding name="SimpleHttp">
        <security mode="Transport">
            <transport clientCredentialType="Basic"/>
        </security>
    </binding>
</basicHttpBinding>

<endpoint address="https://mymachine/routingservice.svc"
          binding="basicHttpBinding" 
          contract="TheContract" 
          name="MyEndpoint" 
          bindingConfiguration="SimpleHttp"/>

Служба маршрутизации (конечная точка службы):

<services>
    <service behaviorConfiguration="routingConfiguration"
          name="System.ServiceModel.Routing.RoutingService">
        <endpoint address=""
              binding="basicHttpBinding"
              name="RoutingServiceEndpoint"
              contract="System.ServiceModel.Routing.IRequestReplyRouter"/>
    </service>
</services>

<basicHttpBinding>
    <binding>
        <security mode="Transport">
            <transport clientCredentialType="None"/>
        </security>
    </binding>
</basicHttpBinding>

<serviceBehaviors>
    <behavior name="routingConfiguration">
        <!-- leaving out the filter details for now, since it's match all -->
        <routing filterTableName="filterTable1" />
    </behavior>
</serviceBehaviors>

Служба маршрутизации (конечная точка клиента):

<client>
    <endpoint name="realDestination"
              address="https://externalwebservice/service/"
              binding="basicHttpBinding"
              bindingConfiguration="otherBasicHttpBinding"
              behaviorConfiguration="CredWriter"
              contract="*" />
</client>

<basicHttpBinding>
    <binding name="otherBasicHttpBinding">
        <security mode="Transport">
            <transport clientCredentialType="Basic"/>
        </security>
    </binding>
</basicHttpBinding>

<endpointBehaviors>
    <behavior name="CredWriter">
        <soapProcessing processMessages="false"/>
        <myCredentialAdder/>
    </behavior>
</endpointBehaviors>

<extensions>
    <behaviorExtensions>
        <add name="myCredentialAdder" type="Assembly Info here."/>
    </behaviorExtensions>
</extensions>

Предполагая, что я не упускаю что-то очевидное, все это должно работать и идти своим путем, передавая информацию по https туда и обратно от клиента к маршрутизатору во внешнюю службуи назад.(Большое предположение)

Вместо этого мне представили следующее исключение и трассировку стека:

System.ServiceModel.CommunicationException: 
An error occurred while receiving the HTTP response to https://mymachine/routingservice.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. ---> 
System.Net.WebException: The underlying connection was closed: 
An unexpected error occurred on a receive. ---> 
System.IO.IOException: Unable to read data from the transport connection: 
An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: 
An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception 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.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)
   //calls to my code were here.

Увидев это, я еще немного покопался в этом и провел все через Fiddler, чтобы увидеть, что происходит.вкл.

Мое клиентское приложение вызывает мою службу маршрутизации на IIS через https и ждет.Служба маршрутизации, размещенная в IIS, обращается к внешней службе.Здесь вещи стали странными.Существует https 200, который показывает новый «объект», возвращаемый в мыльном конверте, другой https 200, который также возвращает еще один новый «объект» из службы, а затем мой звонок из моего клиентского приложения получает 504 Gateway Timeout почтиточное время, когда второй запрос возвращается из внешнего сервиса.

Эта настройка дает мне новое исключение:

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.5720000. 
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 remote server returned an error: (504) Gateway Timeout. 
---> System.Net.WebException: The remote server returned an error: (504) Gateway Timeout.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception 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)
   --- End of inner exception stack trace ---

Server stack trace: 
   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.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)
   //calls to my code

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

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

...