最近跟高老师讨论nginx跟tomcat集群做负载均衡方案。感觉很有意思。想到自己项目中服务用的WCF技术,于是就想WCF如何做负载均衡,Google了一会,发现wcf4.0的路由服务好像可以实现。不过在研究路由服务期间,我有了个自己的方案,哈哈。

我要在客户端跟WCF服务中间部署一台WCF平衡服务器,用来分发请求,模拟nginx的工作。

WCF平衡服务器我同样用WCF来实现,所有服务接口全部通过平衡服务区暴露给客户端。对于客户端来说,只要跟正常调用服务一样,添加平衡器的远程服务引用。

实现:

1.平衡服务类库

namespace WcfSimpleBalance
{
/// <summary>
/// 负载均衡基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class WcfBalance<T>
{
private ChannelFactory<T> _channelFactory; public T BalanceProxy { get; set; } public WcfBalance(string serviceName)
{
string endpoint = EndpointBalance.GetBalanceEndpoint(serviceName);//获取随机endpoint
this._channelFactory = new ChannelFactory<T>(endpoint);
this.BalanceProxy = this._channelFactory.CreateChannel();
}
}
}

其中泛型T为协定,这样就能动态构建wcf的通道了。

namespace WcfSimpleBalance
{
internal class EndpointBalance
{
/// <summary>
/// 平衡节点配置
/// </summary>
private static List<WcfBalanceSection> _wcfBalanceCfg;
static EndpointBalance()
{
_wcfBalanceCfg = ConfigurationManager.GetSection("wcfBalance") as List<WcfBalanceSection>;
} /// <summary>
/// 随机一个Endpoint
/// </summary>
/// <param name="serviceName"></param>
/// <returns></returns>
public static string GetBalanceEndpoint(string serviceName)
{
var serviceCfg = _wcfBalanceCfg.Single(s=>s.ServiceName==serviceName);
var ran = new Random();
int i = ran.Next(0, serviceCfg.Endpoints.Count);
string endpoint = serviceCfg.Endpoints[i];
Console.WriteLine(endpoint);
return endpoint;
}
}
}
这个类提供一个静态方法可以根据服务名称从配置文件中配置的endpoint,并且从中随机一个。随机数的算法可能分布不是特别均匀,不知有什么好的办法。
namespace WcfSimpleBalance
{
    /// <summary>
/// 配置模型
/// </summary>
internal class WcfBalanceSection
{
public string ServiceName { get; set; } public List<string> Endpoints { get; set; }
}
    /// <summary>
/// 自定义配置处理
/// </summary>
public class WcfBalanceSectionHandler : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
var config = new List<WcfBalanceSection>();
foreach (XmlNode node in section.ChildNodes)
{
if (node.Name != "balanceService")
throw new ConfigurationErrorsException("不可识别的配置项", node);
var item = new WcfBalanceSection();
foreach (XmlAttribute attr in node.Attributes)
{
switch (attr.Name)
{
case "ServiceName":
item.ServiceName = attr.Value;
break;
case "Endpoints":
item.Endpoints = attr.Value.Split(',').ToList();
break;
default:
throw new ConfigurationErrorsException("不可识别的配置属性", attr);
}
}
config.Add(item);
}
return config;
}
}
}
这2个是用来处理配置文件的。

2.普通的WCF服务

协定:
namespace WcfServiceContracts
{
[ServiceContract(Name = "CalculatorService")]
public interface IAdd
{
[OperationContract]
int Add(int x, int y);
}
}

一个简单的加法。

wcf服务实现:
namespace WcfService
{
public class AddServices:IAdd
{
public int Add(int x, int y)
{
return x + y;
}
}
}

3.WCF平衡器实现

同样新建一个wcf服务类库,引用同样的协定,引用上面的平衡类库

namespace WcfServiceBalance
{
public class AddServices : WcfBalance<IAdd>, IAdd
{
public AddServices()
: base("AddServices")
{
} public int Add(int x, int y)
{
return BalanceProxy.Add(x, y);
}
}
}

继承WcfBalance跟协定接口。构造函数调用基类的构造函数,传入服务名称。Add实现直接调用基类的方法。

模拟:

1.wcf服务器寄宿

WCF服务可以寄宿在多个方案下面,IIS,win服务,控制台。这里为了方便直接寄宿在控制台下。

新建2个控制台程序,一个寄宿普通的wcf服务。一个寄宿wcf平衡服务。代码不表,给出服务地址。

3个普通的服务。(把寄宿普通服务的控制台程序的bin目录复制3份,改3个端口就成了3个服务)

http://localhost:8081/Wcf

http://localhost:8082/Wcf

http://localhost:8083/Wcf

平衡服务

http://localhost:8088/WcfBalance

配置文件

在平衡服务器的配置文件中定义所有后台服务器的endpoint,然后在自定义wcfBalance节点中配置,服务名对应的endpoint列表用逗号分隔。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="wcfBalance" type="WcfSimpleBalance.WcfBalanceSectionHandler, WcfSimpleBalance" />
</configSections>
<wcfBalance>
<balanceService ServiceName="AddServices" Endpoints="AddService1,AddService2,AddService3" />
</wcfBalance>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_CalculatorService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8081/Wcf" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_CalculatorService"
contract="WcfServiceContracts.IAdd" name="AddService1" />
<endpoint address="http://localhost:8082/Wcf" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_CalculatorService"
contract="WcfServiceContracts.IAdd" name="AddService2" />
<endpoint address="http://localhost:8083/Wcf" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_CalculatorService"
contract="WcfServiceContracts.IAdd" name="AddService3" />
</client>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

2.客户端调用

添加平衡服务器引用,然后用代码调用。

启动30个线程去跑服务。

namespace WcfServiceClient
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 30; i++)
{
var thread = new Thread(new ThreadStart(CallAdd));
thread.Start();
}
Console.Read();
} private static void CallAdd()
{
using (var proxy = new CalculatorServiceClient())
{
proxy.Add(1,2);
}
}
}
}

运行结果:

请求被分布到3个服务上面,不过貌似不太均匀,这个跟算法有关系。

通过以上我们实现了一个简单的wcf平衡服务器,这只是一个简单的方案,肯定有很多很多问题没有考虑到,希望大家指出讨论。

不过我想虽然实现了请求的分发,但是面对真正的高并发环境,平衡服务器会不会成为另外一个瓶颈。

(转)简易WCF负载均衡方案的更多相关文章

  1. 大数据时代下的SQL Server第三方负载均衡方案----Moebius测试

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...

  2. Openfire 集群部署和负载均衡方案

    Openfire 集群部署和负载均衡方案 一.   概述 Openfire是在即时通讯中广泛使用的XMPP协议通讯服务器,本方案采用Openfire的Hazelcast插件进行集群部署,采用Hapro ...

  3. Windows平台下利用APM来做负载均衡方案 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...

  4. (转)大数据时代下的SQL Server第三方负载均衡方案----Moebius测试

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...

  5. asp.net负载均衡方案[转]

    在前面的几篇文章中,主要谈到了在Discuz!NT中的跨站缓存数据,数据库负载均衡.但如果要实现将产品分布式布置到若干机器,组成集群来共同支撑起整个业务的话,还是有一定问题的(后面会有所介绍).下面先 ...

  6. 高可用性的负载均衡方案之lvs+keepalived和haproxy+heartbeat区别

    高可用性的负载均衡方案 目前使用比较多的就是标题中提到的这两者,其实lvs和haproxy都是实现的负载均衡的作用,keepalived和heartbeat都是提高高可用性的,避免单点故障.那么他们为 ...

  7. MySQL数据库读写分离、读负载均衡方案选择

    MySQL数据库读写分离.读负载均衡方案选择 一.MySQL Cluster外键所关联的记录在别的分片节点中性能很差对需要进行分片的表需要修改引擎Innodb为NDB因此MySQL Cluster不适 ...

  8. mysql负载均衡方案

    mysql负载均衡方案 一.直接连接 数据库的读写分离方案很多,这里介绍基于mysql数据库的读写分离方案. 比较常见的读写分离方案如下: 1 基于查询分离 最简单的分离方法是将读和写分发到主和从服务 ...

  9. 【转载】Windows平台下利用APM来做负载均衡方案 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...

随机推荐

  1. Android之来历

    Android一词的本义指“机器人”,同时也是谷歌于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统.中间件.用户界面和应用 软件组成,号称是首个为移动终端打造的 ...

  2. Xcode7 iOS9网络配置

    iOS9为了增强数据访问安全,将所有的http请求都改为了https,为了能够在iOS9中正常使用地图SDK,请在"Info.plist"中进行如下配置,否则影响SDK的使用. & ...

  3. C# \\u8888类型的unicode转换为字符串方法

    1.双斜杠\\ 处理: 2.将编码分组,将编码转换为int,再转换为char. string sss = "\\u6c88\\u9633"; '; string[] arr = a ...

  4. 随笔: WC2016感想

    在某些时刻,我可以体会到非常复杂的情感,这种情感神秘的来源不能被描述.它非常的复杂.你无法分清,这种情感是来源于一个个神经元控制的情感系统的一时冲动,亦或是你如实地反馈了你所正在感知的外界. 但我曾在 ...

  5. uva 296 - Safebreaker

    枚举法 #include <cstdio> using namespace std; int main() { int t, n, i, j, k; scanf("%d" ...

  6. zip命令的用法

    语法zip [参数] [打包后的文件名] [打包的目录路径] 参数列表-a 将文件转成ASCII模式-F 尝试修复损坏的压缩文件-h 显示帮助界面-m 将文件压缩之后,删除源文件-n 特定字符串,不压 ...

  7. OC高级编程——深入block,如何捕获变量,如何存储在堆上

    OC高级编程——深入block,如何捕获变量,如何存储在堆上   首先先看几道block相关的题目 这是一篇比较长的  博文 ,前部分是block的测试题目,中间是block的语法.特性,block讲 ...

  8. Zookeeper,也要接触起来啦

    分布式的东东,就是部署也方便,但管理,想法,大集群应用是要点...! 参考如下URL简单实现 ,以后应用时多留意. http://blog.csdn.net/shirdrn/article/detai ...

  9. C#反射 获取程序集信息和通过类名创建类实例(转载)

    C#反射获取程序集信息和通过类名创建类实例 . System.Reflection 命名空间:包含通过检查托管代码中程序集.模块.成员.参数和其他实体的元数据来检索其相关信息的类型. Assembly ...

  10. 2014.6.14模拟赛【bzoj1646】[Usaco2007 Open]Catch That Cow 抓住那只牛

    Description Farmer John has been informed of the location of a fugitive cow and wants to catch her i ...