0

我正在使用 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

这是我的代码片段:

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();

所以在我的场景中ServiceOperation2并且ServiceOperation3是备份端点,我做了很多研究我找不到以编程方式添加备份列表的方法

任何想法如何将备份列表添加到 filterTable?

4

2 回答 2

2

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

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

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();

希望对某人有所帮助

于 2017-12-20T17:06:40.870 回答
1

我从来没有这样做过,但是快速浏览一下 MSDN 上的消息过滤器文档会发现,备用备份端点是通过FilterTableElementEntry类(BackupList 属性)配置的。

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

检查 Google 上的 Filter Table 和 BackupList,你会遇到使用这个的例子。这个例子看起来特别有前途,有很多描述这些步骤的评论。

于 2017-12-19T15:17:02.250 回答