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

时间:2016-04-20 11:41:37

标签: wcf azure-service-fabric

尝试使用服务结构中的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地址?

2 个答案:

答案 0 :(得分:1)

在我的团队中,这些天我们一直在服务面料中使用wcf。首先,我们尝试使用WcfCommunicationListener形式Microsoft.ServiceFabric.Services.Wcf,但最后我们决定使用我们自己的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 Service中的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
       }
     }
    }

答案 1 :(得分:0)

我唯一能想到的是手动创建基于此示例的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