WCF4.0支持路由机制,通过RoutingService实现请求分发、拦截处理。
一、应用场景
1、暴露一个endpoint在外网,其余服务部署于内网;
2、请求分发,能对服务做负载功能;
二、WCF4.0 路由服务
图1- WCF路由示意图
WCF RoutingService使用了消息过滤器的功能,内置定义了6个过滤器满足不同的需求:
1、ActionMessageFilter:满足指定的操作集之一,也就操作匹配;
2、EndpointAddressMessageFilter:满足指定的终结点地址;
3、XPathMessageFilter:使用 XPath指定匹配的条件,用于实现基于内容路由的核心消息过滤器;
4、MatchAllMessageFilter 与所有消息相匹配;
5、MatchNoneMessageFilter 与所有消息都不匹配;
对于以上默认提供的过滤器不能满足需求,还可以通过创建自己的 MessageFilter 实现消息过滤器。如下我们通过一个demo实现wcf服务分发负载处理。
三、WCF RoutingService负载处理请求
1、创建一个WCF服务,名称为:Aden.FK.WcfServiceA,基于console hosting实现,创建两个ServiceHost。
(1)接口定义和实现为:
1
2
3
4
5
6
7
8
9
|
[ServiceContract]
public
interface
IWcfServiceA
{
[OperationContract]
int
GetNumber();
[OperationContract]
string
GetString();
}
|
(2)服务的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
class
WcfServiceA : IWcfServiceA
{
public
int
GetNumber()
{
string
msg =
"Service :"
+ OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri;
Console.WriteLine(
string
.Format(
"print: {0}"
, msg));
return
new
Random().Next();
}
public
string
GetString()
{
string
msg =
"Service :"
+ OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri;
Console.WriteLine(
string
.Format(
"print: {0}"
, msg));
return
msg;
}
}
|
(3)创建服务host:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int
num = 2;
int
index = 0;
List<ServiceHost> serviceHost =
new
List<ServiceHost>();
for
(
int
i = 1; i <= num; i++)
{
serviceHost.Add(
new
ServiceHost(
typeof
(WcfServiceA)));
}
serviceHost.ToList().ForEach(u =>
{
var
netTcp =
new
NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
u.AddServiceEndpoint(
typeof
(IWcfServiceA), netTcp,
string
.Format(
"net.tcp://127.0.0.1:910{0}/services/WcfServiceA{1}"
, ++index, index));
u.Open();
Console.WriteLine(
"{0} Service Start,Address is {1}"
, u.Description.Name, u.Description.Endpoints[0].Address.Uri);
}
);
|
2、创建一个路由服务,自定义扩展实现MessageFilter进行请求分发,路由与服务之间以TCP协议传输。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
var
serverEndpoints =
new
List<ServiceEndpoint>();
var
netTcp =
new
NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
serverEndpoints.Add(
new
ServiceEndpoint(
new
ContractDescription(
"IWcfServiceA"
), netTcp,
new
EndpointAddress(
"net.tcp://127.0.0.1:9101/services/WcfServiceA1"
)));
serverEndpoints.Add(
new
ServiceEndpoint(
new
ContractDescription(
"IWcfServiceA"
), netTcp,
new
EndpointAddress(
"net.tcp://127.0.0.1:9102/services/WcfServiceA2"
)));
using
(
var
router =
new
ServiceHost(
typeof
(RoutingService)))
{
int
index = 10;
string
routerAddress =
"net.tcp://127.0.0.1:8101/router/routerendpoint"
;
router.AddServiceEndpoint(
typeof
(IRequestReplyRouter), netTcp, routerAddress);
var
config =
new
RoutingConfiguration();
LoadBalancerFilter.EndpointsNumber = 2;
serverEndpoints.ForEach(x => config.FilterTable.Add(
new
LoadBalancerFilter(),
new
[] { x }, index--));
router.Description.Behaviors.Add(
new
RoutingBehavior(config));
var
debugBehavior = router.Description.Behaviors.Find<ServiceDebugBehavior>();
debugBehavior.IncludeExceptionDetailInFaults =
true
;
if
(router.State != CommunicationState.Opening)
router.Open();
while
(Console.ReadKey().Key == ConsoleKey.Enter)
{
break
;
}
router.Close();
}
|
3、创建一个客户端,客户端与路由之间以TCP协议传输。
1
2
3
4
5
6
7
8
|
var
endpoint =
new
EndpointAddress(
"net.tcp://127.0.0.1:8101/router/routerendpoint"
);
var
netTcp =
new
NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
var
client = ChannelFactory<IWcfServiceA>.CreateChannel(netTcp, endpoint);
while
(Console.ReadKey().Key == ConsoleKey.Enter)
{
Console.WriteLine(
"--"
+ client.GetNumber());
}
|
四、运行结果
1、客户端调用
2、服务端显示,每次将请求分发到不同的服务处理。
五、总结
以上是一个简单的路由服务例子,可以根据实际情况扩展路由功能,实现上述描述是应用场景。考虑到路由的压力,可以在路由前架上Nginx负载。