使用WS-MetadataExchange为外部客户端和WcfTestClient公开来自Service Fabric的WCF / TCP端点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用WS-MetadataExchange为外部客户端和WcfTestClient公开来自Service Fabric的WCF / TCP端点相关的知识,希望对你有一定的参考价值。

我有一个无状态服务,我正在迁移一些CloudService WCF端点。这些enpoints可以公开获得,并要求我能够通过Visual Studio项目以及WCFTestClient中的References> Add Service Reference使用WS-MetadataExchange发现它们的属性。

我已经按照一些教程设置了测试端点:

 <Endpoint Protocol="tcp" Name="WcfServiceEndpoint" Type="Input" Port="8081" />

以及服务合同

[ServiceContract]
public interface ITestContract
{
    [OperationContract]
    int TestMethod(int value1, int value2);
}

方法:

public class TestService : ITestContract
{
    public int TestMethod(int value1, int value2)
    {
        var result = value1 + value2;
        return result;
    }
}

并且服务侦听器覆盖:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {

return new[] { new ServiceInstanceListener((context) =>
    new WcfCommunicationListener<ITestContract>(
        this.Context,
        new TestService(),
        WcfUtility.CreateTcpClientBinding(),
        "WcfServiceEndpoint"
    )
)};

在我之前的项目(我正在迁移)中,我设置了自定义ServiceHost对象,并能够自定义其绑定/ Urls。我能够让客户发现服务很好。我需要能够以相同的方式公开此服务,以便WcfTestClient以及References> Add Service Reference可以使用WS-MetadataExchange发现它们的属性。就目前而言,我甚至无法控制服务路径是什么!

理想情况下,我仍然希望使用ServiceHost:

var host = new ServiceHost(ITestContract);
host.AddServiceEndpoint(TestService, new NetTcpBinding(SecurityMode.None), "net.tcp://...", new Uri("net.tcp://..."));
host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
host.Open();

UPDATE

基于VipulM-MSFT(下文)的建议,我现在首先创建通信监听器:

var testCommunicationListener = new WcfCommunicationListener<ITestContract>(
    this.Context,
    new TestService(),
    WcfUtility.CreateTcpClientBinding(),
    "WcfServiceEndpoint"
);

然后修改ServiceHost对象以允许MetadataExchange行为:

ServiceMetadataBehavior metaDataBehavior = new ServiceMetadataBehavior();
testCommunicationListener.ServiceHost.Description.Behaviors.Add(metaDataBehavior);

除了允许故障中的异常细节:

testCommunicationListener.ServiceHost.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
testCommunicationListener.ServiceHost.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });

然后我创建一个服务端点(带有我所需的服务路径):

testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(ITestContract), new NetTcpBinding(SecurityMode.None), "net.tcp://localhost:8081/Services/Tests", new Uri("net.tcp://localhost:8081/Services/Tests"));

以及MexEndpoint(允许通过TCP进行MetaExchange绑定):

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));

最后我将监听器分配给无状态服务:

return new[] { new ServiceInstanceListener((context) => testCommunicationListener)};

当我将其推送到我的本地群集时,我收到以下错误:

该服务包含多个具有不同ContractDescriptions的ServiceEndpoints,每个ContractDescription都具有Name ='ITestContract'和Namespace ='http://tempuri.org/'。为ContractDescriptions提供唯一的名称和命名空间,或者确保ServiceEndpoints具有相同的ContractDescription实例。

我想也许我需要删除默认端点以避免这种冲突所以我试过:

 testCommunicationListener.ServiceHost.Description.Endpoints.RemoveAt(0);

在致电之前:

testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(ITestContract), new NetTcpBinding(SecurityMode.None), "net.tcp://localhost:8081/Services/Tests", new Uri("net.tcp://localhost:8081/Services/Tests"));
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));

这给了我以下错误:

副本在API调用中有多个失败:IStatelessServiceInstance.Open(); Error = System.NullReferenceException(-2147467261)对象引用未设置为对象的实例。在Microsoft.ServiceFabric.Services.Communication.Wcf.Runtime.WcfCommunicationListener1.b__0(IAsyncResult ar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar,Func2 endFunction, Action1 endAction,Task`1 promise,Boolean requiresSynchronization)

我尝试过其他一些类似的结果......

我还尝试在默认绑定上允许MetadataExchange行为(不创建任何其他端点)。但在这种情况下,我如何知道我的端点网址是什么?我尝试使用net.tcp:// localhost:8081 / TestService(应该是默认设置)但我无法从控制台应用程序或WcfTestClient连接到此。


更新2

只需添加MetadataExchangeBinding作为附加端点并在以下内容中分配我想要的服务路径,我就可以根据需要托管我的WCF端点:

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
testCommunicationListener.ServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "net.tcp://localhost:8081/Services/Tests/mex", new Uri("net.tcp://localhost:8081/Services/Tests/mex"));
答案

您可以通过访问主机属性在打开通信侦听器之前自定义ServiceHost。

https://docs.microsoft.com/en-us/dotnet/api/microsoft.servicefabric.services.communication.wcf.runtime.wcfcommunicationlistener-1#Microsoft_ServiceFabric_Services_Communication_Wcf_Runtime_WcfCommunicationListener_1_ServiceHost

默认情况下,代码会添加一些行为,包括服务调试和限制行为,因此,如果删除SDK中提供的WCF的客户端堆栈可能无法正常运行。

以上是关于使用WS-MetadataExchange为外部客户端和WcfTestClient公开来自Service Fabric的WCF / TCP端点的主要内容,如果未能解决你的问题,请参考以下文章

极客日报:微信正式宣布开放外部链接;iPhone13预购开启导致苹果官网崩了;特斯拉将向车主提供新版 FSD

Android 仿映客直播间给主播发送礼物(实现连击效果)

菊风中标中国光大银行Call-Center系统之多媒体客服子系统应用升级项目

Nginx反向代理常用配置

网企-6

牛客练习赛83 E.牛客推荐系统开发之标签重复度