WCF路由如何以编程方式添加备份列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WCF路由如何以编程方式添加备份列表相关的知识,希望对你有一定的参考价值。

我正在使用WCF路由服务,我正在尝试实现故障转移,我需要以编程方式添加过滤器表备份列表,这是一个示例配置:

<system.serviceModel>
          <client>
            <endpoint address="http://localhost:8081/Service1" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation1" />
            <endpoint address="http://localhost:8081/Service2" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation2" />
            <endpoint address="http://localhost:8081/Service3" binding="basicHttpBinding"
                      contract="*" name="ServiceOperation3" />
          </client>
          <routing>
            <filters>
              <filter name="MatchAllFilter" filterType="MatchAll" />
            </filters>
            <filterTables>
              <filterTable name="RoutingTable">
                <add filterName="MatchAllFilter" endpointName="ServiceOperation1" backupList="BackUps" />
              </filterTable>
            </filterTables>
            <backupLists>
              <backupList name="BackUps">
                <add endpointName="ServiceOperation2"/>
                <add endpointName="ServiceOperation3" />
              </backupList>
            </backupLists>
          </routing>
          <behaviors>
            <serviceBehaviors>
              <behavior name="">
                <routing filterTableName="RoutingTable" />
              </behavior>
            </serviceBehaviors>
          </behaviors>
            <services>
                <service name="System.ServiceModel.Routing.RoutingService">
                  <endpoint address="binary" binding="basicHttpBinding"
                           contract="System.ServiceModel.Routing.IRequestReplyRouter" name="VirtualEndpoint" />
                    <host>
                        <baseAddresses>
                            <add baseAddress="http://localhost:8080/RoutingService/Router" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
</system.serviceModel>

我能够添加FilterTable,我找到了示例in this question

这是我的代码片段:

var routingHost = new ServiceHost(typeof(RoutingService));
var routingEp = routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, url);      
var filterTable = new MessageFilterTable<IEnumerable<ServiceEndpoint>>();   
filterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint>()
                        {
                            serviceoperation1Endpoint
                        });


 routingHost.Description.Behaviors.Add(
                              new RoutingBehavior(new RoutingConfiguration(filterTable, false)));

routingHost.open();

所以在我的场景中ServiceOperation2ServiceOperation3是备份端点,我进行了大量的研究,我找不到以编程方式添加备份列表的方法

任何想法如何将backuplist添加到filterTable?

答案

我从来没有这样做,但快速浏览MSDN上Message Filters的文档显示,通过FilterTableElementEntry类(BackupList属性)配置备用备份端点。

筛选器表是FilterTableEntryElement对象的命名集合,用于定义筛选器,主目标端点和备用备份端点列表之间的关联。过滤器表条目还允许您为每个过滤条件指定可选的优先级。

检查Google上的过滤表和BackupList,您会看到使用此示例的示例。 This example看起来特别有希望,有很多评论描述了这些步骤。

另一答案

我最终得到了这个动态生成配置文件的解决方案

在我的场景中,我从数据库加载端点并从中生成路由服务配置,

public class MyServiceEndPoint 
{
    public string TypeName { get; set; }

    public string Url { get; set; }

    public string Name { get; set; }
}

//// generates routing service configuration section, including client enoints/filterTable/backups and routing service behavior
private void CreateRoutingConfiguration(List<MyServiceEndPoint> serviceEndpoints)
{
     ///// group endopints by Name, each service could have multiple endpoints ( 1 main and n backup endpoints)
    var groupedEndpoitns = (from endp in serviceEndpoints
                                    group endp by endp.Name into endpGroup
                                    select new { ServiceName = endpGroup.Key, EndPoint = endpGroup }).ToList();



    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    var serviceModelSectionGroup = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);

    var routingSection = (RoutingSection)serviceModelSectionGroup.Sections["routing"];
    var clientsection = (ClientSection)serviceModelSectionGroup.Sections["client"];
    var bindingSection = (BindingsSection)serviceModelSectionGroup.Sections["bindings"];
    var behaviorSection = (BehaviorsSection)serviceModelSectionGroup.Sections["behaviors"];

    bindingSection.NetTcpBinding.Bindings.Clear();
    clientsection.Endpoints.Clear();
    var filterTable = new FilterTableEntryCollection() { Name = "RoutingTable" };
    routingSection.Filters.Clear();
    routingSection.FilterTables.Clear();
    routingSection.BackupLists.Clear();

    var nettcpBinding = new NetTcpBindingElement()
    {
        Name = "myTcpBinding",
        TransferMode = TransferMode.Buffered,
        MaxBufferSize = 2147483647,
        MaxReceivedMessageSize = 2147483647,        
        SendTimeout = new TimeSpan(0, 10, 0),
        ReceiveTimeout = new TimeSpan(0, 10, 0),

    };

    nettcpBinding.Security.Mode = SecurityMode.None;
    bindingSection.NetTcpBinding.Bindings.Add(nettcpBinding);


    foreach (var endpointGroup in groupedEndpoitns)
    {
        var backupListItem = new BackupEndpointCollection();
        backupListItem.Name = endpointGroup.ServiceName + "Backup";

        var filter = new FilterElement();
        filter.Name = endpointGroup.ServiceName + "Filter";
        filter.FilterType = FilterType.Custom;
        filter.CustomType = "MyServiceContractMessageFilterType,asemblyName";
        filter.FilterData = endpointGroup.EndPoint.FirstOrDefault().ClientTypeName;
        routingSection.Filters.Add(filter);

        int endpointCount = 0;
        List<ChannelEndpointElement> channelEndpoints = new List<ChannelEndpointElement>();
        foreach (var endpoint in endpointGroup.EndPoint)
        {
            endpointCount++;
            var channelEndpoint = new ChannelEndpointElement();
            channelEndpoint.Address = new Uri(endpoint.Url);
            channelEndpoint.Binding = "netTcpBinding";
            channelEndpoint.BindingConfiguration = "myTcpBinding";
            channelEndpoint.Contract = "*";
            channelEndpoint.Name = $"{endpoint.Name}EndPoint{endpointCount}";
            clientsection.Endpoints.Add(channelEndpoint);
            channelEndpoints.Add(channelEndpoint);

        }

        var firstChannelEndpoint = channelEndpoints.FirstOrDefault(); /// this endpoint will be selected as main endpoint
        var filterTableItem = new FilterTableEntryElement();
        filterTableItem.FilterName = filter.Name;
        filterTableItem.EndpointName = firstChannelEndpoint.Name;
        filterTableItem.BackupList = backupListItem.Name;
        filterTable.Add(filterTableItem);    

        foreach (var backupEndpoints in channelEndpoints)
        {
            backupListItem.Add(new BackupEndpointElement() { EndpointName = backupEndpoints.Name });
            routingSection.BackupLists.Add(backupListItem);
        }
    }

    routingSection.FilterTables.Add(filterTable);    
    behaviorSection.ServiceBehaviors.Clear();
    var behavior = new ServiceBehaviorElement();
    behavior.Add(new RoutingExtensionElement() { FilterTableName = filterTable.Name });
    behaviorSection.ServiceBehaviors.Add(behavior);
    config.Save(ConfigurationSaveMode.Modified, false);
    ConfigurationManager.RefreshSection("system.serviceModel/routing");
    ConfigurationManager.RefreshSection("system.serviceModel/client");        
ConfigurationManager.RefreshSection("system.serviceModel/behaviors");
}

所以首先我生成配置文件,然后创建路由服务的实例,如:

CreateRoutingConfiguration(serviceEndpoints);
routingHost = new ServiceHost(typeof(RoutingService));
routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, $"net.tcp://localhost:6000/Router");
routingHost.Open();

希望它对某人有所帮助

以上是关于WCF路由如何以编程方式添加备份列表的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将按钮添加到片段

以编程方式添加终结点标头安全 WCF

如何在没有 XML 的情况下以编程方式将片段添加到活动

如何以编程方式配置 WCF 已知类型?

如何以编程方式为 WCF 服务创建自签名证书?

如何以编程方式将客户端连接到 WCF 服务?