Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 外部客户端无法访问Azure服务结构上的WCF通信侦听器_C#_Wcf_Azure_Azure Service Fabric - Fatal编程技术网

C# 外部客户端无法访问Azure服务结构上的WCF通信侦听器

C# 外部客户端无法访问Azure服务结构上的WCF通信侦听器,c#,wcf,azure,azure-service-fabric,C#,Wcf,Azure,Azure Service Fabric,我正在尝试使用WCF通信侦听器将运行WCF的Azure Web角色迁移到Azure Service Fabric中的无状态服务。在我的本地服务集群中,一切都正常。发布到Azure后,群集中的其他服务可以访问无状态WCF服务,但外部(internet)客户端(包括我的开发人员计算机)无法连接到暂时的网络错误 我验证了资源组中的负载平衡器具有端口80和8080的规则/探测,并使用TCP和HTTP进行了测试。我还尝试在WCF客户机上设置分区解析器,以指向服务集群上的“客户机连接端点”(默认情况下,它在

我正在尝试使用WCF通信侦听器将运行WCF的Azure Web角色迁移到Azure Service Fabric中的无状态服务。在我的本地服务集群中,一切都正常。发布到Azure后,群集中的其他服务可以访问无状态WCF服务,但外部(internet)客户端(包括我的开发人员计算机)无法连接到暂时的网络错误

我验证了资源组中的负载平衡器具有端口80和8080的规则/探测,并使用TCP和HTTP进行了测试。我还尝试在WCF客户机上设置分区解析器,以指向服务集群上的“客户机连接端点”(默认情况下,它在服务集群中工作)

此时,我不确定是否存在配置问题,或者外部(internet)客户端是否可能连接到运行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;
        };
    }
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;
        };
ServiceManifest.xml(我还使用了各种端口的默认TCP绑定)

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;
    }
公共静态WcfServiceFabricCommunicationClient GetClient(Uri地址,绑定)
{
//ServicePartitionResolver.GetDefault();可与群集中的其他服务一起使用
var partitionResolver=newservicepartitionresolver(“:8080”);
var wcfClientFactory=new WcfCommunicationClientFactory(binding,null,partitionResolver);
var sfclient=新的WcfServiceFabricCommunicationClient(wcfClientFactory、地址、ServicePartitionKey.Singleton);
归还客户;
}
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)
    {

    }
}
公共类WcfServiceFabricCommunicationClient:ServicePartitionClient其中T:class
{
公共WcfServiceFabricCommunicationClient(ICommunicationClientFactory CommunicationClient Factory,
Uri服务Uri,
ServicePartitionKey partitionKey=null,
TargetReplicaSelector TargetReplicaSelector=TargetReplicaSelector.Default,
字符串listenerName=null,
OperationRetrySettings retrySettings=null
)
:base(communicationClientFactory、serviceUri、partitionKey、TargetReplicaseSelect、listenerName、retrySettings)
{
}
}

以下是一种使用
WebHttpBinding的WCF服务的方法:

尝试更改代码,使其不使用包含显式URL的
endpointResourceName
,而是使用
address
。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);

以下是一种适用于具有
WebHttpBinding
的WCF服务的方法:

尝试更改代码,使其不使用包含显式URL的
endpointResourceName
,而是使用
address
。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);

这是我根据LoekD的答案更新的代码

服务更改: 要使服务对internet客户端可用,您必须向WCFCommunicationListener添加一个“Address”属性,以告知服务要侦听的端点(或)

客户端更改:使用普通WCF客户端,不使用任何WCFCommunicationListener引用。仅在服务结构内部使用WCFCommunicationListener客户端(在这种情况下,我的原始代码可以正常工作)

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;
        };
    }
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客户端示例:

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;
        }
    }
}
公共抽象类WcfWebClient其中T:class
{
公共静态TResult InvokeRestMethod(Func方法、绑定绑定、端点地址)
{
var myChannelFactory=新的ChannelFactory(绑定,地址);
var wcfClient=myChannelFactory.CreateChannel();
尝试
{
var结果=方法(wcfClient);
((IClientChannel)wcfClient.Close();
返回结果;
}
捕获(超时异常e)
{
Trace.TraceError(“WCF客户端超时异常”+e.Message);
//处理超时异常。
((IClientChannel)wcfClient.Abort();
投掷;
}
捕获(通信异常e)
{
Trace.TraceError(“WCF客户端通信异常”+e.Message);
//处理通信异常。
((IClientChannel)wcfClient.Abort();
投掷;
}
}
}

这是我根据LoekD的答案更新的代码

服务更改: 要使服务对internet客户端可用,您必须向WCFCommunicationListener添加一个“Address”属性,以告知服务要侦听的端点(或)

客户端更改:使用普通WCF客户端,不使用任何WCFCommunicationListener引用。仅在服务结构内部使用WCFCommunicationListener客户端(在这种情况下,我的原始代码可以正常工作)

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;
        };
    }
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客户端示例:

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;
        }
    }
}
公共抽象类WcfWebClient其中T:class
{
公共静态TResult InvokeRestMethod(Func方法、绑定绑定、端点地址)
{
var myChannelFactory=新的ChannelFactory(绑定,地址);
var wcfClient=myChannelFactory.CreateChannel();
尝试
{
var结果=方法(wcfClient);
((IClientChannel)wcfCli