3

基本認証を使用して、安全な外部 SOAP Web サービスに接続する必要があるシナリオがあります。通常、これは問題ではなく、私のローカル開発環境では basicHttpBinding で動作します。アプリが展開されると、アプリは DMZ に置かれ、世界に発信するためのアクセス権がなくなります。これにより、内部ネットワークでルーティング サービスが必要になり、WCF 4.0 の新しいルーティング機能が適切な候補のように思えました。ルーティング サービスを介して PoC として http 経由で別の外部サービスへの呼び出しを行うコードを取得し、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 ホステッド ルーティング サービスは、外部サービスを呼び出します。これは物事が奇妙になった場所です。新しい「エンティティ」が SOAP エンベロープで返されることを示す https 200 があり、サービスから別の新しい「エンティティ」を返す別の https 200 があり、クライアント アプリからの呼び出しでほぼ 504 ゲートウェイ タイムアウトが発生します。 2 番目の要求が外部サービスから返された正確な時刻。

このセットアップは私に新しい例外を与えます:

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

例外が示唆するようにタイムアウトを上げようとしましたが、これは数分ではなく 1 秒か 2 秒で失敗したため、うまくいきませんでした。したがって、この問題の例やその他の解決策を探してインターネットを精査した後、この時点で、これが失敗する理由、潜在的な問題、または同じことを達成しようとしている人に答えるものを見つけることができませんでしたもの。

コミュニティの皆さんが、私がまだ解決していない問題を見つけて、すでにこの問題を自分で解決しており、喜んで解決策を共有してくれること、またはバインディングやセットアップの問題を簡単に見つけられることを願っています。

4

0 に答える 0