2016-07-07 5 views
1

WCF通信リスナーを使用して、AzureサービスファブリックのステートレスサービスにWCFを実行するAzure Webロールを移行しようとしています。すべて私のローカルサービスクラスターで動作します。 Azureに公開した後、クラスタ内の他のサービスはステートレスWCFサービスにアクセスできますが、外部(インターネット)クライアント(my devマシンを含む)は一時的なネットワークエラーで接続できません。外部クライアントがAzureサービスファブリックのWCF通信リスナーにアクセスできない

リソースグループ内のロードバランサにポート80と8080のルール/プローブがあり、TCPとHTTPでテスト済みであることを確認しました。また、WCFクライアント上のパーティションリゾルバをセットアップして、サービスクラスタ内の "クライアント接続エンドポイント"(デフォルトではサービスクラスタ内で動作する)をポイントしようとしました。

この時点では、構成上の問題があるかどうか、または外部(インターネット)クライアントがWCF通信リスナーを実行しているステートレスサービスに接続することが可能かどうかはわかりません。ここで

は私の設定です:

WCFコミュニケーションリスナー

private Func<StatelessServiceContext, ICommunicationListener> CreateListener() 
    { 
     return delegate (StatelessServiceContext context) 
     { 

      var host = new WcfCommunicationListener<IHello>(
       wcfServiceObject: this, 
       serviceContext: context, 
       endpointResourceName: "ServiceEndpoint", 
       listenerBinding: CreateDefaultHttpBinding() 
      ); 
      return host; 
     }; 
    } 

WCF ServiceManifest.xml

public static Binding CreateDefaultHttpBinding() 
    { 
     var binding = new WSHttpBinding(SecurityMode.None) 
     { 
      CloseTimeout = new TimeSpan(00, 05, 00), 
      OpenTimeout = new TimeSpan(00, 05, 00), 
      ReceiveTimeout = new TimeSpan(00, 05, 00), 
      SendTimeout = new TimeSpan(00, 05, 00), 
      MaxReceivedMessageSize = int.MaxValue, 
     }; 
     var quota = new XmlDictionaryReaderQuotas 
     { 
      MaxArrayLength = int.MaxValue, 
      MaxDepth = int.MaxValue 
     }; 
     binding.ReaderQuotas = quota; 
     return binding; 
    } 

をバインド(私はデフォルトのTCPをも使用しましたさまざまなポートとのバインディング)

<Endpoints> 
    <Endpoint Name="ServiceEndpoint" Protocol="http" Port="8080" /> 
</Endpoints> 

WCFコンソールアプリケーション

var address = new Uri("fabric:/ServiceFabricWcf.Azure/ServiceFabricWcf"); 
var client = GetClient(address, CreateDefaultHttpBinding()); 

try 
    { 
    var results = client.InvokeWithRetry(x => x.Channel.Hello()); 
    System.WriteLine($"Results from WCF Service: '{results}'"); 
    Console.ReadKey(); 
    } 
    catch (Exception e) 
    { 
    System.Console.WriteLine("Exception calling WCF Service: '{e}'"); 
    } 

WCFクライアント

public static WcfServiceFabricCommunicationClient<IHello> GetClient(Uri address, Binding binding) 
    { 
     //ServicePartitionResolver.GetDefault(); Works with other services in cluster 
     var partitionResolver = new ServicePartitionResolver("<clientConnectionEndpointOfServiceCluster>:8080"); 
     var wcfClientFactory = new WcfCommunicationClientFactory<IHello>(binding, null, partitionResolver); 
     var sfclient = new WcfServiceFabricCommunicationClient<IHello>(wcfClientFactory, address, ServicePartitionKey.Singleton); 
     return sfclient; 
    } 

WCFクライアント工場

public class WcfServiceFabricCommunicationClient<T> : ServicePartitionClient<WcfCommunicationClient<T>> where T : class 
{ 
    public WcfServiceFabricCommunicationClient(ICommunicationClientFactory<WcfCommunicationClient<T>> communicationClientFactory, 
               Uri serviceUri, 
               ServicePartitionKey partitionKey = null, 
               TargetReplicaSelector targetReplicaSelector = TargetReplicaSelector.Default, 
               string listenerName = null, 
               OperationRetrySettings retrySettings = null 
               ) 
     : base(communicationClientFactory, serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings) 
    { 

    } 
} 

答えて

0

ここWebHttpBindingとWCFサービスのために働く方法です:https://github.com/loekd/ServiceFabric.WcfCalc

それはendpointResourceNameしかしaddress代わりに、明示的なURLを含むを使用しないようにコードを変更してみてください。 URLは、mycluster.region.cloudapp.azure.comのように、クラスタのパブリック名である必要があります。

編集:URLはノード名を使用する方が簡単です。

string host = context.NodeContext.IPAddressOrFQDN; 
    var endpointConfig = context.CodePackageActivationContext.GetEndpoint  
    ("CalculatorEndpoint"); 
    int port = endpointConfig.Port; 
    string scheme = endpointConfig.Protocol.ToString(); 
    string uri = string.Format(CultureInfo.InvariantCulture, 
    "{0}://{1}:{2}/", scheme, host, port); 
+0

ありがとうございます。 WsHttpBindingを保持し、投稿したHTTP URI形式を使用してWCFコミュニケーションリスナーに「アドレス」を追加することができました。ローカルで動作し、Azure Service Fabricに公開されたときに動作します。このシナリオ(インターネットアクセス)では、通常のWCFクライアントを使用することができます(内部のみを想定した例ではありません) – Rioprelude

0

LoekDの答えに基づいて、私の更新コードです。

サービスの変更: は、インターネットクライアントにサービスを利用できるようにするには、あなたが(http://mycluster.region.azure.comまたはhttp://localhost)をリッスンするようにどのようなエンドポイントサービスを伝えるためにWCFCommunicationListenerに「住所」プロパティを追加する必要が

クライアントの変更点:通常のWCFクライアントを使用し、WCFCommunicationListener参照は一切使用しません。サービス・ファブリック内にWCFCommunicationListenerクライアントのみを使用してください(このシナリオでは、私の元のコードが正常に動作します)。

WCFサーバーのリスナー

return delegate (StatelessServiceContext context) 
     { 
      string host = HostFromConfig(context); 
      if (string.IsNullOrWhiteSpace(host)) 
      { 
       host = context.NodeContext.IPAddressOrFQDN; 
      } 

      var endpointConfig = context.CodePackageActivationContext.GetEndpoint("ServiceEndpoint"); 
      int port = endpointConfig.Port; 
      string scheme = endpointConfig.Protocol.ToString(); 
      //http://mycluster.region.cloudapp.azure.com or http://localhost 
      string uri = string.Format(CultureInfo.InvariantCulture, "{0}://{1}:{2}", scheme, host, port); 

      var listener = new WcfCommunicationListener<IHello>(
       wcfServiceObject: this, 
       serviceContext: context, 
       listenerBinding: CreateDefaultHttpBinding(), 
       address: new EndpointAddress(uri) 
      ); 
      return listener; 
     }; 

WCFクライアントアプリケーション

static void Main(string[] args) 
    { 
     System.Console.WriteLine("\nPress any key to start the wcf client."); 
     System.Console.ReadKey(); 

     System.Console.WriteLine("*************Calling Hello Service*************"); 
     try 
     { 
      var binding = CreateDefaultHttpBinding(); 
      var address = new EndpointAddress("http://cluster.region.cloudapp.azure.com/"); //new EndpointAddress("http://localhost"); 
      var results = WcfWebClient<IHello>.InvokeRestMethod(x => x.Hello(),binding, address); 

      System.Console.WriteLine($"*************Results from Hello Service: '{results}'*************"); 
      Console.ReadKey(); 
     } 
     catch (Exception e) 
     { 
      System.Console.WriteLine($"*************Exception calling Hello Service: '{e}'*************"); 
     } 
    } 

WCFバインディング

public static Binding CreateDefaultHttpBinding() 
{ 
    var binding = new WSHttpBinding(SecurityMode.None) 
    { 
     CloseTimeout = new TimeSpan(00, 05, 00), 
     OpenTimeout = new TimeSpan(00, 05, 00), 
     ReceiveTimeout = new TimeSpan(00, 05, 00), 
     SendTimeout = new TimeSpan(00, 05, 00), 
     MaxReceivedMessageSize = int.MaxValue, 
    }; 
    var quota = new XmlDictionaryReaderQuotas 
    { 
     MaxArrayLength = int.MaxValue, 
     MaxDepth = int.MaxValue 
    }; 
    binding.ReaderQuotas = quota; 
    return binding; 
} 

サンプル外部/インターネットWCFクライアント:

public abstract class WcfWebClient<T> where T : class 
{ 
    public static TResult InvokeRestMethod<TResult>(Func<T, TResult> method, Binding binding, EndpointAddress address) 
    { 
     var myChannelFactory = new ChannelFactory<T>(binding, address); 
     var wcfClient = myChannelFactory.CreateChannel(); 

     try 
     { 
      var result = method(wcfClient); 
      ((IClientChannel)wcfClient).Close(); 
      return result; 
     } 
     catch (TimeoutException e) 
     { 
      Trace.TraceError("WCF Client Timeout Exception" + e.Message); 
      // Handle the timeout exception. 
      ((IClientChannel)wcfClient).Abort(); 
      throw; 
     } 
     catch (CommunicationException e) 
     { 
      Trace.TraceError("WCF Client Communication Exception" + e.Message); 
      // Handle the communication exception. 
      ((IClientChannel)wcfClient).Abort(); 
      throw; 
     } 
    } 
} 
0

また、サービスの実装に次の属性を置くことにより、WCFサービスのための任意のアドレスバインディングモードを有効にしようとすることができます:

[ServiceBehavior(AddressFilterMode = AddressFilterMode .Any)]

関連する問題