本帖最后由 天若有情 于 2014-6-16 14:02 编辑
' h9 l+ k, I; G. R# { {
' Q2 S, J! R1 A! s- W 本文将向大家介绍如何托管内部WCF服务和公共WCF服务,为了托管内部WCF服务,需要建立一个内部端点,并使用内部角色通信,与在输入端点上托管一个外部服务最主要的区别是内部端点不具有负载均衡特性,而输入端点是挂钩在负载均衡器上的,具有负载均衡功能。% F* Q$ D7 `: G/ T) `
托管内部WCF服务
4 _& ~. P- D0 }' Q 其实要托管一个内部WCF服务很简单,唯一需要注意的是传递给 ServiceHost 的基地址不同,因为端口号和IP地址要等到运行时才知道,因此需要创建一个主机,动态地传递这些信息给它。
8 T) w$ y: G) N* I5 r) m5 e public override bool OnStart()
: X; @+ Z0 Z6 c& f7 H2 `; T J {+ ?' B- w- g3 I# p6 | ~
// 设置最大并发连接数
1 r9 h4 j, J9 i' n/ v4 O) @9 | ServicePointManager.DefaultConnectionLimit = 12;
, I q/ [/ Q1 a9 U. z DiagnosticMonitor.Start(“DiagnosticsConnectionString”);: } o8 U' ?* W9 K, B$ V$ z
// For information on handling configuration changes( W$ ~, i6 S/ ?6 [- q5 ?5 ?
// see the MSDN topic at =166357.
) k9 V; R2 T9 d! H& K6 D, b- J RoleEnvironment.Changing += RoleEnvironmentChanging;- @5 }) Q M. g; d0 a5 S
StartWCFService();
2 ^" @8 J0 C4 Q9 Y" w6 s return base.OnStart();
* d( z7 K# P- W( K; P5 [ }+ o* P. B1 a4 B" G
private void StartWCFService()
% L, `+ @' G" r B ~! f5 h' I {
6 E" L5 f$ y: B1 o var baseAddress = String.Format(
* N/ ^' ?9 n3 D: _ “net.tcp://{0}”,% s0 s7 _ j6 f8 t; }$ d
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[雨林木风系统“EchoService”].IPEndpoint! `3 c: _7 N! g9 i4 M5 a9 e% \
);. _: |8 Z1 R% s8 `" J* `
var host = new ServiceHost(typeof(EchoService), new Uri(baseAddress));
0 z; o: v# i) @; M( } host.AddServiceEndpoint(typeof(IEchoService), new NetTcpBinding(SecurityMode.None), “echo”);
, ~: r9 t8 K% L8 E: p( w; N host.Open();( u4 `5 {1 m% ]; P) D8 b/ P- Y9 C
使用内部WCF服务
6 `0 O& }% H) w3 h0 x' X 我想从我另一个托管的服务调用这个服务,下面就是调用这个服务的所有代码:
0 x" ~9 j- {1 E5 s protected void Button1_Click(object sender, EventArgs e)
l/ x8 y: x i {) A* k. v( x3 |% f$ b7 h
var factory = new ChannelFactory(new NetTcpBinding(SecurityMode.None));
, } T# X# Y. R X5 w# s+ [+ a% [ var channel = factory.CreateChannel(GetRandomEndpoint());. W4 j4 Q# n I9 Y8 f5 ?
Label1.Text = channel.Echo(TextBox1.Text);
8 r/ Z4 u% Q) Z5 A7 v }# u! v+ x* F) N7 t. ?% A
private EndpointAddress GetRandomEndpoint()
7 F/ X2 ?0 [+ F* r$ v* U3 s' ~" \1 L {1 v, ~0 @+ l( j* B( |+ S
var endpoints = RoleEnvironment.Roles[“WorkerHost”].Instances
3 b' D! ?! Z7 J2 Q* i4 I# q2 X .Select(i =》 i.InstanceEndpoints[“EchoService”])! g% A' |$ G! c
.ToArray();+ p' {" W9 g# _7 |$ y# [" B
var r = new Random(DateTime.Now.Millisecond);, I4 S v! i9 H
return new EndpointAddress(
% i" b& |, m# t" B% a, H0 e String.Format(
/ D, o: n4 I* S) J3 d$ o5 n1 W “net.tcp://{0}/echo”,3 _; X7 J7 l9 B9 A$ L, j( n5 s
endpoints[r.Next(endpoints.Count() - 1)].IPEndpoint)
2 Q( f1 |2 S8 R+ a );8 ~+ E7 q7 q# F% B
}- W( A# J$ K% Z; M! D, k
这里唯一要注意的是查询F abric ,确定 WorkerHost 角色中实现了 EchoService 端点,深度系统官网并随机给它们路由请求的所有端点,本来不需要路由请求,我这样做是因为内部端点没有负载均衡功能,我希望在每个 WorkerHost 实例上均匀地分配负载。
+ Y( J/ r( R2 f% J1 q; C, R, J3 H( d- I 我发现一个技巧,就是不需要缓存你找到的 IPEndpoint ,因为它已经缓存在API调用中,但根据最佳实践,你应该缓存你的 ChannelFactory 。
! t& D3 C2 `( E 托管公共WCF服务
2 A# e, f' o& Q. a: r" U 托管公共WCF服务也很简单,唯一需要注意的是要使用一个新的行为,为MEX端点处理负载均衡,此外,在你的服务上需要包括一个类属性处理地址过滤不匹配问题。
. j& v( R1 j7 s: ?, X5 x |