天蓝色服务结构 wcf 端点地址 net.tcp 而不是 http

Posted

技术标签:

【中文标题】天蓝色服务结构 wcf 端点地址 net.tcp 而不是 http【英文标题】:azure service fabric wcf endpoint address net.tcp instead of http 【发布时间】:2016-08-13 01:36:48 【问题描述】:

尝试在服务结构中使用 wcf 设置有状态的可靠服务,我复制了以下示例代码:

protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()

    return new[]  new ServiceReplicaListener((context) =>
    new WcfCommunicationListener<IService1>(
        wcfServiceObject:this,
        serviceContext:context,            
        endpointResourceName: "ServiceEndpoint",
        listenerBinding: WcfUtility.CreateTcpListenerBinding()
    )
);

在 ServiceManifest.xml 我已经声明了端点:

  <Resources>
    <Endpoints>
      <Endpoint Name="ServiceEndpoint" Protocol="http" Port="8100" />   
      <Endpoint Name="ReplicatorEndpoint" />
    </Endpoints>
  </Resources>

但是当我部署到本地集群,并在 Service Fabric Explorer 中查看运行服务的节点时,端点有这个地址:

net.tcp://localhost:8100/455d1c74-7734-449b-a567-47b749b3b822/88af6851-0285-4989-b0aa-c0cbe8c2d06a-131056235989980581

如何获取 http 地址?

【问题讨论】:

关键是您的 listenerBinding 属性是使用 WcfUtility.CreateTcpListenerBinding() 分配的。我想这是目前唯一可能的方法,因为 WcfUtility 中没有其他方法,但是看看这个链接,也许它会对你有所帮助:azure.microsoft.com/en-us/documentation/articles/… 感谢您的回复,我怀疑是监听器绑定的问题。您引用的页面是我从中获取代码的地方:-)。我还没有找到任何其他关于在 wcf 中使用服务结构的文档。 【参考方案1】:

在我的团队中,这些天我们一直在使用服务结构中的 wcf。首先,我们尝试使用 Microsoft.ServiceFabric.Services.Wcf 形式的 WcfCommunicationListener,但最后我们决定使用我们自己的 ICommunicationListener 实现,以便更好地控制服务主机。我们还使用 net.tcp 作为绑定而不是 http。我们以编程方式定义行为和端点,而不是使用 app.config。 我将分享我们的方法。希望对您有所帮助。

第一步,ICommunicationListener 实现:

public class ServiceHostCommunicationListener : ICommunicationListener

    private string baseAddress;

    public ServiceHost Host  get; set; 

    public ServiceHostCommunicationListener(ServiceHost host, string baseAddress)
    
        Host = host;
        this.baseAddress = baseAddress;
    

    public void Abort()
    
        Host.Abort();
    

    public async Task CloseAsync(CancellationToken cancellationToken)
    
        try
        
            await Task.Factory.FromAsync(Host.BeginClose(null, null), ar =>
            
                Host.EndClose(ar);
            );
        
        catch (Exception)
        
            Host.Abort();
        
    

    public Task<string> OpenAsync(CancellationToken cancellationToken)
    
        return Task.Factory.FromAsync(Host.BeginOpen(null, null), ar =>
        
            Host.EndOpen(ar);
            return baseAddress;
        );
    

第二步,在我们的 Service Fabric 服务中的 CreateServiceInstanceListeners 中创建监听器的实例。这里是我创建服务主机实例、它的端点和行为的地方。

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    
        yield return new ServiceInstanceListener(context =>
        
            return CreateListener(context);
        );
    

    private ICommunicationListener CreateListener(StatelessServiceContext context)
    
        Uri baseUri = new Uri($"net.tcp://configuration.Network.BaseAddress");

        ServiceHost serviceHost = new ServiceHost(new SampleService(), baseUri);
        InitServiceDebugBehavior(serviceHost);
        if (configuration.Network.MetadataAddress != null)
        
            AddMetadataEndpoint(baseUri, serviceHost);
        
        InitServerCertificate(serviceHost);
        AddServiceEndpoint(serviceHost);

        return new ServiceHostCommunicationListener(serviceHost, baseUri.AbsoluteUri);
    


    private void InitServiceDebugBehavior(ServiceHost host)
    
        var serviceDebug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
        if (serviceDebug == null)
        
            serviceDebug = new ServiceDebugBehavior();
            host.Description.Behaviors.Add(serviceDebug);
        
        serviceDebug.IncludeExceptionDetailInFaults = configuration.ServiceBehavior.ServerDebug.IncludeExceptionDetailInFaults;
    

    private void AddMetadataEndpoint(Uri baseUri, ServiceHost serviceHost)
    
        ServiceMetadataBehavior smb = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (smb == null)
        
            smb = new ServiceMetadataBehavior();
            serviceHost.Description.Behaviors.Add(smb);
        
        serviceHost.AddServiceEndpoint(
            ServiceMetadataBehavior.MexContractName,
            MetadataExchangeBindings.CreateMexTcpBinding(),
            configuration.Network.MetadataAddress
        );
    

    private void InitServerCertificate(ServiceHost host)
    
        var serverCertificateConfig = configuration.ServiceBehavior.ServerCertificate;
        host.Credentials.ServiceCertificate.SetCertificate(
            serverCertificateConfig.Store,
            StoreName.My,
            serverCertificateConfig.FindType,
            serverCertificateConfig.FindValue
            );
    

    private void AddServiceEndpoint(ServiceHost serviceHost)
    
        var binding = new NetTcpBinding(SecurityMode.Transport);
        binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
        serviceHost.AddServiceEndpoint(typeof(SampleService), binding, configuration.Network.ServiceAddress);
    

这是配置文件,以防您有任何疑问。我们将其存储在 PackageRoot-Config 文件夹中。

    
     "Network": 
       "BaseAddress": "localhost:1020/SampleService/",
       "ServiceAddress": "service",
       "MetadataAddress": "mex"
       ,
     "ServiceBehavior": 
       "ServerCertificate": 
       "Store": "LocalMachine",
       "FindType": "FindBySubjectDistinguishedName",
       "FindValue": "CN=mycert.deploy.com"
       ,
     "ServerDebug": 
       "IncludeExceptionDetailInFaults": true
       
     
    

【讨论】:

【参考方案2】:

我唯一能想到的就是手动创建基于此示例的 Http 绑定:

BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
            
                SendTimeout = TimeSpan.MaxValue,
                ReceiveTimeout = TimeSpan.MaxValue,
                OpenTimeout = TimeSpan.FromSeconds(5),
                CloseTimeout = TimeSpan.FromSeconds(5),
                MaxReceivedMessageSize = 1024 * 1024
            ;
            binding.MaxBufferSize = (int)binding.MaxReceivedMessageSize;
            binding.MaxBufferPoolSize = Environment.ProcessorCount * binding.MaxReceivedMessageSize;
            return binding;

使用该绑定,地址是服务结构资源管理器中的 http

【讨论】:

以上是关于天蓝色服务结构 wcf 端点地址 net.tcp 而不是 http的主要内容,如果未能解决你的问题,请参考以下文章

在 WCF 的添加服务引用中找不到 net.tcp 端点?

如何使用来自远程服务器的 net.tcp 端点 ping 或检查 WCF 服务的状态?

无法连接到我的Localhost上的WCF服务

WCF Net.tcp 仅在本地失败

wsFederationHttpBinding over net.tcp

WCF - 在 net.tcp://..../Querier.svc 上没有可以接受消息的端点侦听