windows NLB实现MSSQL读写分离--从数据库集群读负载均衡

主从模式,几乎大部分出名的数据库都支持的一种集群模式。数据库

当Web站点的访问量上去以后,不少站点,选择读写分离,减轻主数据库的的压力。固然,一主多从也能够做用多个功能,好比备份。这里主要演示如何实现从数据库集群的读负载均衡服务器

搭建一主三从的MSSQL集群负载均衡

192.168.99.250  //主服务器

192.168.99.8  //从服务器(WIN-6S3JNU8C4TB)
192.168.99.10  //从服务器(WIN-HF1GQ5U288H)
192.168.99.11  //从服务器(WIN-EAPJ2QB5AGM)

本地发布dom

通常而言,咱们只须要安装数据库引擎服务便可。复制服务须要另外安装,因此咱们进行发布/订阅模式的话,须要安装复制组件ide

192.168.99.250 主服务器发布数据同步,接三台从服务器订阅发布。post

本地订阅测试

一样本地订阅,也须要安装复制组件。ui

 

模拟写数据加密

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using System.Text;
using System.Linq;

namespace Write
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始写入模拟数据");
            var ef = new EFDbContext();
            var rand = new Random();
            StringBuilder str1 = new StringBuilder();
            str1.Append("赵、钱、孙、李、周、吴、郑、王、冯、陈、楮、卫、蒋、沈、韩、杨、朱、秦、尤、许、何、吕、施、张、孔、曹");
            var familyNameItems = str1.ToString().Split("");

            StringBuilder str2 = new StringBuilder();
            str2.Append("宏子 婷婷 蓉蓉 丽娜 娜 钰 天霞 官君 红梅 淑慧 海娟 洪山 ");
            str2.Append("盼丽 艳红 甜甜 璨 彬彬 银红 晨曦 婷 广荣 蓓 小艳 欣如 辅仁 嘉 雯婷 玉红 晨霞 ");
            str2.Append("涵 明 丽娜 青 茵 瑞微 逸群 思阳 臻 勇 志光 克涛 靖华 慧霞 卫伟 藜文 清华 莎 晓新 ");
            str2.Append("安安 荌荌 安卉 安娜 安妮 安然 傲冬 傲晴 傲雪 白雪 白云 碧螺 碧菡 碧玉 冰蓝 ");
            str2.Append("含烟 含玉 涵菡 晗蕾 涵韵 晗玥 寒凝 寒香 寒雁 和悌 和美 和怡 和雅 和璧 和玉 ");
            str2.Append("红螺 虹雨 虹彩 虹英 虹颖 虹影 怀玉 慧心 慧颖 慧雅 慕青 问兰 尔岚 元香 曼文");
            var firstNameItems = str2.ToString().Split(" ");

            while (true)
            {
                string userName = "15" + rand.Next(100000000, 999999999).ToString();
                ef.OAUser.Add(new OAUser
                {
                    UserName = userName,
                    PassWord = "123456",
                    Salt = rand.Next(1111111, 6666666).ToString(),
                    NickName = familyNameItems[rand.Next(0, familyNameItems.Count())]
                    + firstNameItems[rand.Next(0, firstNameItems.Count())],
                    IsFrozen = false,
                    CreateTime = DateTime.Now
                });
                ef.SaveChanges();
                Console.WriteLine($"成功将用户{userName}资料写入");
            }
        }
    }

    public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            base.ChangeTracker.AutoDetectChangesEnabled = false;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=192.168.99.250;Initial Catalog=Test;User Id=sa;Password=123;",
                n => n.UseRowNumberForPaging());
        }

        /// <summary>
        /// 用户表
        /// </summary>
        public DbSet<OAUser> OAUser { set; get; }
    }

    /// <summary>
    /// 用户表
    /// </summary>
    [Table("OAUser")]
    public class OAUser
    {
        /// <summary>
        /// 主健
        /// </summary>
        [Key]
        public int Id { set; get; }

        /// <summary>
        /// 用户帐号
        /// </summary>
        [Required, MaxLength(15), MinLength(6)]
        public string UserName { set; get; }

        /// <summary>
        /// 用户密码
        /// </summary>
        [Required, StringLength(64)]
        public string PassWord { set; get; }

        /// <summary>
        /// 昵称
        /// </summary>
        [Required, StringLength(30)]
        public string NickName { get; set; }

        /// <summary>
        /// 加密盐
        /// </summary>
        [Required, StringLength(20)]
        public string Salt { set; get; }

        /// <summary>
        /// 是否冻结
        /// </summary>
        public bool IsFrozen { set; get; }

        /// <summary>
        /// 建立时间
        /// </summary>
        public DateTime CreateTime { set; get; }
    }
}

 搭建NLB集群spa

192.168.99.120 //公共IP

192.168.99.8
192.168.99.10
192.168.99.11

模拟读取数据库

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using System.Text;
using System.Linq;

namespace Read
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("模拟大量读取");
            var ef = new EFDbContext();
            var i = 0;
            while (i < 1000)
            {
                i++;
                var user = ef.OAUser.OrderBy(n => Guid.NewGuid()).Take(1).FirstOrDefault();
                Console.WriteLine($"读取用户{user.UserName}资料");
            }
            Console.WriteLine("读取完毕");
        }
    }

    public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            base.ChangeTracker.AutoDetectChangesEnabled = false;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=192.168.99.120;Initial Catalog=oa;User Id=sa;Password=123;",
                n => n.UseRowNumberForPaging());
        }

        /// <summary>
        /// 用户表
        /// </summary>
        public DbSet<OAUser> OAUser { set; get; }
    }

    /// <summary>
    /// 用户表
    /// </summary>
    [Table("OAUser")]
    public class OAUser
    {
        /// <summary>
        /// 主健
        /// </summary>
        [Key]
        public int Id { set; get; }

        /// <summary>
        /// 用户帐号
        /// </summary>
        [Required, MaxLength(15), MinLength(6)]
        public string UserName { set; get; }

        /// <summary>
        /// 用户密码
        /// </summary>
        [Required, StringLength(64)]
        public string PassWord { set; get; }

        /// <summary>
        /// 昵称
        /// </summary>
        [Required, StringLength(30)]
        public string NickName { get; set; }

        /// <summary>
        /// 加密盐
        /// </summary>
        [Required, StringLength(20)]
        public string Salt { set; get; }

        /// <summary>
        /// 是否冻结
        /// </summary>
        public bool IsFrozen { set; get; }

        /// <summary>
        /// 建立时间
        /// </summary>
        public DateTime CreateTime { set; get; }
    }
}

 

通过屡次测试发现,每次只在一台从服务器上面进行读取,纳闷

后来输出发现

Console.WriteLine(con.ClientConnectionId);

链接ID同样,从新启动,刚链接ID会有变更,而后果另外一个从服务器进行大量读取。

 初步猜想,应该是链接池的搞的鬼,若是关闭链接,可是实际上,并无关闭数据库链接,而是归还链接池。从新打开数据库,又重链接池分配一条链接。

目前不清楚链接池的分配规则,从结果来看,应该是每次都是分配了相同的程序池链接。

 如今暂进不测了,下班走,改天,部署WEB结构,而后用压力测试测试,看看数据库读取是否均衡。

相关文章
相关标签/搜索