我正在使用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();
所以在我的场景中ServiceOperation2
和ServiceOperation3
是备份端点,我进行了大量的研究,我找不到以编程方式添加备份列表的方法
任何想法如何将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();
希望它对某人有所帮助