• 使用windows服务和MSMQ和进行日志管理(解决高并发问题)


    首先,建立一个windows服务项目

    image

    然后进行设计视图

    image 

    在工作区空白处右属,添加一个安装项目

    image

    然后就可以写我们的代码了,我们的服务需要实时监视MSMQ的队列中有没有记录,如果有,就向数据库中插入

    核心代码如下

    /// <summary>
    /// 接收来自MSMQ的消息,并保存到数据库
    /// </summary>
    public class MessageQueueService
    {
        public static bool blnStopThread;
        public static string exTemp = string.Empty;
    
        public MessageQueueService()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }
    
        public static void Start()
        {
            string queuePath = ".\Private$\zzl";
            IsQueueExists(queuePath);
            MessageQueue myQueue = new MessageQueue(queuePath);
    
            myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(Log) });
    
            do
            {
                try
                {
                    // Receive and format the message.
                    Message myMessage = myQueue.Receive(); //当消息队列空时,线程会挂起
                    Log log = (Log)myMessage.Body;
    
                    if (log == null) return;
    
                    Save(log);//保存到数据库,此处略详细代码
                }
                catch (System.Exception ex)
                {
                    //异常处理
                    //……
                }
            } while (blnStopThread == false);
        }
    
        private static void IsQueueExists(string path)
        {
            if (!MessageQueue.Exists(path))
            {
                MessageQueue.Create(path);
            }
        }
    
      
    
    private static void Save(Log entity)
          {
              using (SqlConnection sqlconn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["conn"].ToString()))
              {
                  using (SqlCommand sqlcomm = new SqlCommand(
                      "INSERT INTO [Web_Logs]([LogID],[FromURL],[ExeSQL],[FromSystem],[HttpMethod],[OccurTime],[info]) VALUES (@LogID,@FromURL,@ExeSQL,@FromSystem,@HttpMethod,@OccurTime,@Info);"
                      , sqlconn))
                  {
                      SqlParameter parameter = new SqlParameter("@ExceptionID", SqlDbType.VarChar, 36);
                      parameter.Value = Guid.NewGuid().ToString();
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@LogID", SqlDbType.VarChar, 36);
                      parameter.Value = entity.ID;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@FromURL", SqlDbType.VarChar, 200);
                      parameter.Value = string.Empty;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@ExeSQL", SqlDbType.VarChar, 1000);
                      parameter.Value = string.Empty;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@FromSystem", SqlDbType.Int);
                      parameter.Value = 1;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@HttpMethod", SqlDbType.VarChar, 50);
                      parameter.Value = string.Empty;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@Info", SqlDbType.VarChar, 50);
                      parameter.Value = entity.Info;
                      sqlcomm.Parameters.Add(parameter);
    
                      parameter = new SqlParameter("@OccurTime", SqlDbType.DateTime);
                      parameter.Value = entity.OccerTime;
                      sqlcomm.Parameters.Add(parameter);
    
                      sqlconn.Open();
                      sqlcomm.ExecuteNonQuery();
                      sqlconn.Close();
                  }
              }
          }
    
    public class Log
    {
        public string ID { get; set; }
    
        public string Info { get; set; }
    
        public DateTime OccerTime { get; set; }
    
        public void PrintAll()
        {
            Console.WriteLine("{0}  {1}  {2}", ID, Info, OccerTime);
        }
    }

    为了使服务实时对MSMQ进行监控,需要我们在服务中使用一个定时事件,代码如下:

    当然在程序初始化时,需要为一个System.Timers.Timer类型进行相应的初始化工作

       this.timer1 = new System.Timers.Timer();
          this.timer1.Start();
          this.timer1.Interval = 1000;
          this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);

    这个WINDOWS服务我们已经添加完成,现在需要做的就是MSMQ部分了,事实上windows服务这块主要是从MSMQ中得到消息,而在MSMQ这块主要是向MSMQ去写入消息,微软的MSMQ完全支持复杂类型,也就是说你可以将一个类对象写到MSMQ中

    /// <summary>
        /// 日志实体
        /// 可以被序列化
        /// </summary>
        [Serializable()]
        public sealed class Log
        {
            public string ID { get; set; }
    
            public string Info { get; set; }
    
            public DateTime OccerTime { get; set; }
        }
    
        /// <summary>
        /// MSMQ消息功能密封类
        /// 向消息队列中写入日志信息
        /// </summary>
        public sealed class MSMQLog
        {
            private static object sync = new object();
            private static object syncWrite = new object();
            static volatile MessageQueue writer = null;
    
            private static MessageQueue MSQWriter
            {
                get
                {
                    if (writer == null)
                    {
                        lock (sync)
                        {
                            if (writer == null)
                            {
                                string queuePath = ".\Private$\zzl";
                                IsQueueExists(queuePath);
                                writer = new MessageQueue(queuePath);
                            }
                        }
                    }
                    return writer;
                }
            }
    
            private static void IsQueueExists(string path)
            {
                if (!MessageQueue.Exists(path))
                {
                    MessageQueue.Create(path);
                }
            }
    
            public static void Write(Log log)
            {
                lock (syncWrite)
                {
                    MSQWriter.Send(log);
                }
            }
        }

    当需要调用它时,可以这样:

    image

    安装与卸载windows服务的方法:

         installutil工具在目录:系统盘:WINDOWSMicrosoft.NETFrameworkv4.0.30319下,运行cmd,输入

      C:WINDOWSMicrosoft.NETFrameworkv4.0.30319installutil xxxx.exe 回车,即可完成windows服务的安装。

      卸载则为输入 C:WINDOWSMicrosoft.NETFrameworkv4.0.30319installutil /u xxxx.exe 回车。

    本例经过自己实验,已经成功,当若干客户端同时进行某种操作时,可以同时写入数据库中,这就是我要说的,进行window服务和MSMQ技术实现高并发的解决方案

  • 相关阅读:
    BFC是什么?如何形成BFC,有什么作用?
    z-index 有什么作用? 如何使用?
    有几种定位方式?分别是如何实现定位的?参考点是什么?使用场景是什么?
    Promise
    token
    文档碎片
    ECharts常用配置项
    for each()和map()的区别
    window.onload和$(docunment).ready的区别
    密码的两种常用加密方式
  • 原文地址:https://www.cnblogs.com/kingCpp/p/4881708.html
Copyright © 2020-2023  润新知