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