(转)简易WCF负载均衡方案

最近跟高老师讨论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负载均衡方案

时间: 2024-10-26 18:46:56

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

Nginx的负载均衡方案详解

Nginx的负载均衡方案详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Nginx的负载均衡方案有: 1.轮询 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器. 配置的例子如下: http{ upstream sampleapp { server <<dns entry or IP Address(optional with port)>>; server <&l

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

概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效果,可以说还是非常的理想的.同时我们也收集到了不少的问题,比如说如何在这种分布式的架构下使用Session,NLB中有一台服务器挂掉了会导致对外暴露的地址无法访问,如果实现服务器之间的同步,如果更好的进行热修复等等,还有我们在上一篇中也提到了NLB所提供的功能是非常简单的,为了回答我们前面提到的问题

负载均衡方案总结

负载均衡方案总结 所有的例子都通过访问www.ctrip.com为例.这里只讲方案,具体的NGIX.LVS.HAPROXY怎么工作的等以后细看了再总结. HTTP重定向负载均衡 用户通过域名解析, 得到IP地址114.100.80.100,访问这台服务器,这台机器收到请求之后,因为它是知道服务器集群里的IP的, 然后返回一个重定向到114.100.80.1的请求给用户的浏览器,然后浏览器再访问114.100.80.1. 这个方案致命的缺点就是经过了两次请求,因为建立HTTP连接的请求的代价是很大

邮件系统负载均衡方案

负载均衡是集群部署中的一种,通过多个节点来承担邮件服务的工作,每个获取Web页面的新请求都被动态路由到一个负载较低的节点上.即把负载压力根据某种算法合理分配到集群中的每一台计算机上,以减轻主服务器的压力,降低对主服务器的硬件和软件要求,适用于大容量用户使用. 集群技术解析 集群(Cluster)技术是指一组相互独立的计算机,利用高速通信网络组成一个计算机系统,每个群集节点(即集群中的每台计算机)都是运行其自己进程的一个独立服务器.这些进程可以彼此通信,对网络客户机来说就像是形成了一个单一系统,协

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

在前面的几篇文章中,主要谈到了在Discuz!NT中的跨站缓存数据,数据库负载均衡.但如果要实现将产品分布式布置到若干机器,组成集群来共同支撑起整个业务的话,还是有一定问题的(后面会有所介绍).下面先介绍一下如何使用 Discuz!NT负载均衡方案搭建分布式应用. Discuz!NT前端负载均衡可以是nginx,lvs,haproxy等,当然配置最简单的基于nginx实现的,下面是它的一些简介:           Nginx("engine x")是俄罗斯人编写的十分轻量级的HTTP

负载均衡方案对比表

在选择使用何种负载均衡方案的时候,除了考虑工程师本身的熟练程度外,也要理解技术的原理,透过本质才能更好的看问题,下图参考<Linux运维最佳实践>:

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

一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius(Install) Moebius测试(Testing) 负载均衡测试(Load Balancing Testing) 高可用性测试(Failover Testing) 数据安全性测试(Security Testing) 总结(Summary) 二.背景(Contexts) 前几天在SQL Serve

负载均衡方案(摘抄)

1.负载均衡之DNS域名解析 DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网.人们在通过浏览器访问网站时只需要记住网站的域名即可,而不需要记住那些不太容易理解的IP地址.在DNS系统中有一个比较重要的的资源类型叫做主机记录也称为A记录,A记录是用于名称解析的重要记录,它将特定的主机名映射到对应主机的IP地址上.如果你有一个自己的域名,那么要想别人能访问到你的网站,你需要到特定的DNS解析服务商的服务器上

asp.net如何实现负载均衡方案讨论

我的目标是我一个人搭建一个负载均衡网站.不接受这是网络部,或者运维,或者系统部的事情,所有事情都是我一个人来完成,包括掏钱,包括将来发展等等,同时也别告诉我有没有意义,just do  it !给我方案,给我方法. 拥有资源:不够可以买,多了可以先闲着. 现在我已经买了5台阿里云服务器,ip地址分别为 ip地址                      名字简称      操作系统       iis服务器     cpu   内存DDR3      机械硬盘 111.13.101.204