服务主机的路由器与负载均衡和实现思路

网络 路由交换
WCF中间件的路由功能是在客户端与服务端之间加入中介服务,用来转发它们之间的消息。实现消息的转发可以修改WCF服务消息头的内容,重新指定服务地址即可。

路由器介绍及演示

WCF中间件的路由功能是在客户端与服务端之间加入中介服务,用来转发它们之间的消息。实现消息的转发可以修改WCF服务消息头的内容,重新指定服务地址即可,那给消息头指定的服务地址从哪来,需要给路由器配置服务端地址目录,路由器与服务端肯定不是一对一的,路由器可以指定多个服务端,而路由器把客户端连接指定给哪个服务端这里就有一个算法,算法的优劣就决定了中间件负载均衡的能力。

下面演示了中间件的路由功能,把Out目录中的程序复制6份,分别改名如下,3个客户端,1个路有中间件,2个服务中间件,还要修改每个程序的相关配置;这样先启动路由中间件Router和服务中间件WCFservser1、WCFServer2,然后分别启动2个客户端程序,路由中间件和服务中间件就会显示客户端的连接信息。3个客户端会有2个分配到一个服务中间件,一个客户端分配到另外一个服务中间件,不会说3个客户端都分配到1个服务中间件,这是由路由中间件的负载均衡算法决定的;

 

 

 

 

路由功能的实现

框架增加了一个路由服务对象Router,用它来拦截客户端发送的消息,拦截方法ProcessMessage(Message requestMessage);

首先根据路由目录结合负载均衡的算法取得服务地址endpointAddress,然后创建WCF通道并绑定新的服务地址,调用服务端的方法;

 

  1. /// <summary> 
  2.         /// 截获从Client端发送的消息转发到目标终结点并获得返回值给Client端 
  3.         /// </summary> 
  4.         /// <param name="requestMessage"></param> 
  5.         /// <returns></returns> 
  6.         public Message ProcessMessage(Message requestMessage) 
  7.         { 
  8.             //Binding binding = null
  9.             EndpointAddress endpointAddress = null
  10.             GetServiceEndpoint(requestMessage, out endpointAddress); 
  11.             IDuplexRouterCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexRouterCallback>(); 
  12.             NetTcpBinding tbinding = new NetTcpBinding("netTcpExpenseService_ForSupplier"); 
  13.             using (DuplexChannelFactory<IRouterService> factory = new DuplexChannelFactory<IRouterService>(new InstanceContext(null, new DuplexRouterCallback(callback)), tbinding, endpointAddress)) 
  14.             { 
  15.  
  16.                 factory.Endpoint.Behaviors.Add(new MustUnderstandBehavior(false)); 
  17.                 IRouterService proxy = factory.CreateChannel(); 
  18.  
  19.                 using (proxy as IDisposable) 
  20.                 { 
  21.                     // 请求消息记录 
  22.                     IClientChannel clientChannel = proxy as IClientChannel; 
  23.                     //Console.WriteLine(String.Format("Request received at {0}, to {1}\r\n\tAction: {2}", DateTime.Now, clientChannel.RemoteAddress.Uri.AbsoluteUri, requestMessage.Headers.Action)); 
  24.                     if (Convert.ToInt32(HostSettingConfig.GetValue("debug")) == 1) 
  25.                         hostwcfMsg(DateTime.Now, String.Format("路由请求消息发送:  {0}", clientChannel.RemoteAddress.Uri.AbsoluteUri)); 
  26.                     // 调用绑定的终结点的服务方法 
  27.                     Message responseMessage = proxy.ProcessMessage(requestMessage); 
  28.  
  29.                     // 应答消息记录 
  30.                     //Console.WriteLine(String.Format("Reply received at {0}\r\n\tAction: {1}", DateTime.Now, responseMessage.Headers.Action)); 
  31.                     //Console.WriteLine(); 
  32.                     //hostwcfMsg(DateTime.Now, String.Format("应答消息: {0}", responseMessage.Headers.Action)); 
  33.                     return responseMessage; 
  34.                 } 
  35.             } 
  36.         } 

#p#负载均衡的实现

负载均衡实现代码在Router对象中的GetServiceEndpoint方法中,定义了RegistrationList对象用来存储客户端列表,在消息头中增加了两个标识routerID和CMD,routerID用来识别客户端,值是客户端创建发送到路由中间件,每个客户端只有一个routerID;CMD用来客户端发送给路由中间件的命令标识,这里只用到了一个就是”Quit”就是卸载路由中间件中的RegistrationList客户端列表;

解决了识别客户端的问题,那平均算法每个客户端分配到哪个服务中间件就很简单了,RoundRobinCount就记录每个服务中间件对应的客户端个数,哪个服务中间件数量少新的客户端就分配给它;

 

  1. private void GetServiceEndpoint(Message requestMessage,out EndpointAddress endpointAddress) 
  2.         { 
  3.  
  4.             string ns = "http://www.3yxx.com/"
  5.             string routerID = GetHeaderValue("routerID", ns); 
  6.             string cmd = GetHeaderValue("CMD", ns); 
  7.             string contractNamespace = requestMessage.Headers.Action.Substring(0, requestMessage.Headers.Action.LastIndexOf("/")); 
  8.  
  9.             
  10.  
  11.             RegistrationInfo regInfo = null
  12.  
  13.             if (Router.RoundRobinCount.ContainsKey(routerID)) 
  14.             { 
  15.                 int key = Router.RoundRobinCount[routerID]; 
  16.                 regInfo = Router.RegistrationList[key]; 
  17.                 if (cmd == "Quit") 
  18.                 { 
  19.                     regInfo.ClientNum -1
  20.                 } 
  21.             } 
  22.             else 
  23.             { 
  24.                 //根据指定的协议名称空间从注册表容器中得到注册项列表 
  25.                 var results = from item in Router.RegistrationList 
  26.                               where item.Value.ContractNamespace.Contains(contractNamespace) 
  27.                               orderby item.Value.ClientNum ascending 
  28.                               select item; 
  29.                 if (results.Count<KeyValuePair<int, RegistrationInfo>>() > 0) 
  30.                 { 
  31.                     var val = results.First<KeyValuePair<int, RegistrationInfo>>(); 
  32.                     Router.RoundRobinCount.Add(routerID, val.Key); 
  33.                     val.Value.ClientNum += 1; 
  34.                     regInfo = val.Value; 
  35.                 } 
  36.             } 
  37.  
  38.             Uri addressUri = new Uri(regInfo.Address); 
  39.  
  40.             //binding = CustomBindConfig.GetRouterBinding(addressUri.Scheme); 
  41.             endpointAddress = new EndpointAddress(regInfo.Address); 
  42.             //重设Message的目标终结点 
  43.             requestMessage.Headers.To = new Uri(regInfo.Address); 
  44.  
  45.             hostwcfRouter(RegistrationList.Values.ToList()); 
  46.         } 

WCF客户端配置和中间件配置还有路由地址配置

如果部署的时候不使用中间件的路由功能,那客户端配置服务地址直接指定服务端WCF地址就行了,而如果启用路由功能,那客户端就配置路由中间件的WCF地址,路由中间件再配置路由目录,对应服务端;

客户端WCF配置和服务端WCF配置还有一个地方值得注意,就是netTcpBinding节点的配置;***配置为取消服务器凭据认证,因为如果不配置为None,当客户端断开连接后再连接的时候就会一些安全性验证,导致连接报错,所以对WCF安全性方面的配置没有吃透的话还是先这样配置好;

1)客户端App.Config配置

 

 

 

 

2)路由中间件App.Config配置和路由目录RouterBill.xml配置

 

 

 

 

3)服务中间件App.Config配置

 

 

5.总结

本章我们详细讲解了EFW框架中的WCF中间件的路由功能和负载均衡的实现,代码很简单,但深入理解却没那么容易,我也只是略懂点皮毛,参考了网上资料把功能实现而已,而想要做成专业级别的中间件是有一个过程的,所以不只是我,也需要有兴趣的人一起完善它;

路由实例程序下载 :http://pan.baidu.com/s/1eQ8FscE

注意:实例中的配置文件中的IP地址192.168.1.3修改为你本机的IP地址;

 

责任编辑:林琳 来源: 博客园精华区
相关推荐

2009-12-18 16:05:03

智能型负载均衡

2013-01-16 15:47:33

路由器IP地址负载均衡

2013-03-12 09:36:49

路由器负载均衡路由技术

2010-04-25 18:23:24

负载均衡路由器

2010-05-10 15:12:21

路由器负载均衡

2019-02-21 09:18:27

服务路由负载均衡微服务

2009-12-08 17:49:17

2010-05-04 18:10:07

路由器负载均衡

2009-04-09 09:35:00

多WAN口宽带路由器负载均衡

2009-07-22 10:25:37

2009-01-10 18:53:01

服务器ServerDNS

2018-11-27 12:56:09

负载均衡应用路由

2009-12-09 14:47:54

WAN口宽带路由器

2010-05-05 22:40:21

apache服务器负载均衡

2010-04-22 16:31:09

配置网络负载均衡

2011-11-22 21:26:59

pfSense配置Web服务器负载均衡

2010-11-19 12:53:53

梭子鱼负载均衡

2020-04-15 22:18:55

架构负载均衡分布式

2010-04-22 23:33:48

负载均衡设置

2013-10-24 09:43:39

路由器
点赞
收藏

51CTO技术栈公众号