Example #1
0
 protected void WriteLogMessage(exDb dbContext, int?_Inbound_Id, int?_Outbound_Id, bool _IsError, string _Message, string _Details)
 {
     new LogRecord()
     {
         Source      = this._Name,
         HostId      = this.HostId,
         QueueId     = this.QueueId,
         Inbound_Id  = _Inbound_Id,
         Outbound_Id = _Outbound_Id,
         IsError     = _IsError,
         Message     = _Message,
         Details     = _Details
     }
     .TryWrite(dbContext);
 }
Example #2
0
        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!Monitor.TryEnter(TimerLock) || ShouldStop)
            {
                return;
            }

            using (var exdb = new exDb(dbConnStr)) {
                foreach (var bus in Buses.Where(b => !b.IsConnected))
                {
                    new LogRecord()
                    {
                        Source  = _Name,
                        HostId  = RabbitQueues.FirstOrDefault(q => bus == q.Bus).Host_Id,
                        IsError = true,
                        Message = "Утеряно соединение с сервером RabbitMQ. Выполняются попытки переподключения...",
                        Details = RabbitQueues.FirstOrDefault(q => bus == q.Bus).Host.ConnectionString
                    }
                    .TryWrite(dbConnStr, dbLog);
                }

                foreach (var w in workers)
                {
                    if (!w.IsAlive)
                    {
                        new LogRecord()
                        {
                            Source  = _Name,
                            HostId  = w.HostId,
                            QueueId = w.QueueId,
                            Message = "Обнаружено непредвиденное завершение обработчика очереди сообщений. Перезапускаем обработчик...",
                            Details = w.QueueFullName
                        }
                        .TryWrite(dbConnStr, dbLog);
                        w.Respawn();
                    }
                }
            }

            Monitor.Exit(TimerLock);
        }
Example #3
0
        private void MessageHandler(Byte[] body, MessageProperties mp, MessageReceivedInfo mi)
        {
            using (var exdb = new exDb(dbConnStr)) {
                exdb.Log = dbLog;

                new LogRecord()
                {
                    Source  = this._Name,
                    HostId  = this.HostId,
                    QueueId = this.QueueId,
                    Message = String.Format("Принято сообщение {0} байт", body.Length),
                    Details = this.QueueFullName
                }
                .TryWrite(exdb);

                var msg = Queue.Base64Data ? Convert.ToBase64String(body)
                                        : this.Encoding.GetString(body);

                var record = new Inbound()
                {
                    QueueId      = this.QueueId,
                    DateReceived = DateTime.Now,
                    Message      = msg
                };
                exdb.Inbound.InsertOnSubmit(record);
                // Rethrow = true. Если не удалось записать сообщение в БД, таск должен упасть, чтобы EasyNetQ не отправил Ack раббиту
                exdb.TrySubmitChanges(true);

                new LogRecord()
                {
                    Source     = this._Name,
                    HostId     = this.HostId,
                    QueueId    = this.QueueId,
                    Inbound_Id = record.Message_Id,
                    Message    = String.Format("Записали {0}сообщение в БД", Queue.Base64Data ? "base64 " : ""),
                    Details    = String.Format("{0} символов", msg.Length)
                }
                .TryWrite(exdb);
            }
        }
Example #4
0
        public void Start()
        {
            try {
                Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Exchange_Svc.MyServiceName));
            } catch (Exception ex) {
                Trace.TraceWarning("{2}\t{0}: не удалось создать папку логов: {1}", _Name, ex.Message, DateTime.Now);
            }

            if (DebugFlag.Enabled)
            {
                try {
                    dbLog = new StreamWriter(Path.Combine(Path.GetTempPath(), Exchange_Svc.MyServiceName, "service.dblog"))
                    {
                        AutoFlush = true
                    };
                } catch (Exception ex) {
                    Trace.TraceWarning("{2}\t{0}: не удалось создать журнал dblog: {1}", _Name, ex.Message, DateTime.Now);
                }
            }

            Trace.TraceInformation("{1}\t{0}: запускается...", _Name, DateTime.Now);

            if (dbConnStr == null || String.IsNullOrWhiteSpace(dbConnStr))
            {
                FailStart("Запуск невозможен: строка подключения к БД не может быть пустой");
            }

            using (var SQLconn = new SqlConnection(dbConnStr)) {
                // Пытаемся подключиться к БД
                int errorCounter = 0;
                while (SQLconn.State == ConnectionState.Closed)
                {
                    try {
                        SQLconn.Open();
                    } catch (Exception ex) {
                        if (ex is InvalidOperationException)
                        {
                            FailStart("Запуск невозможен: ошибка в строке подключения к БД \"{0}\"", dbConnStr);
                        }
                        else if (errorCounter >= 3)
                        {
                            FailStart("Превышено допустимое количество неудачных попыток подключения к БД. Последняя ошибка: {0}", ex.Message);
                        }
                        else
                        {
                            errorCounter++;
                            Trace.TraceWarning("{1}\tНеудачная попытка подключения к БД: {0}", ex.Message, DateTime.Now);
                            Thread.Sleep(1000);
                        }
                    }
                }

                // На этом этапе соединение с БД установлено
                try {
                    new LogRecord()
                    {
                        Source  = _Name,
                        Message = "Успешный запуск, установлено соединение с БД",
                        Details = dbConnStr
                    }
                    .TryWrite(SQLconn, dbLog);
                } catch (Exception ex) {
                    FailStart("Запуск невозможен: ошибка записи в БД, {0}", ex.Message);
                }
                // Получаем список хостов RabbitMQ
                using (var exdb = new exDb(SQLconn)) {
                    exdb.Log     = dbLog;
                    RabbitHosts  = exdb.Hosts.Where(h => exdb.Queues.Any(q => q.Host_Id == h.Host_Id)).ToList();
                    RabbitQueues = exdb.Queues.ToList();
                    if (RabbitHosts.Count == 0)
                    {
                        var msg = "В таблице Hosts нет активных записей. Остановка службы";
                        new LogRecord()
                        {
                            Source  = _Name,
                            IsError = true,
                            Message = msg
                        }
                        .TryWrite(exdb);
                        FailStart(msg);
                    }
                }
                // Подключаемся к хостам RabbitMQ
                foreach (var host in RabbitHosts)
                {
                    var rabbit_conn = new ConnectionConfiguration();
                    rabbit_conn.PrefetchCount     = Convert.ToUInt16((host.PrefetchCount > 0) ? host.PrefetchCount : 1);
                    rabbit_conn.PublisherConfirms = true;
                    //r_conn.Port = Convert.ToUInt16((host.Port > 0) ? host.Port : 5671);
                    if (!String.IsNullOrWhiteSpace(host.VirtualHost))
                    {
                        rabbit_conn.VirtualHost = host.VirtualHost;
                    }
                    if (!String.IsNullOrWhiteSpace(host.Username))
                    {
                        rabbit_conn.UserName = host.Username;
                        if (!String.IsNullOrWhiteSpace(host.Password))
                        {
                            rabbit_conn.Password = host.Password;
                        }
                    }

                    var r_host = new HostConfiguration();
                    r_host.Host = host.Host;
                    r_host.Port = Convert.ToUInt16((host.Port > 0) ? host.Port : host.SslEnabled ? 5671 : 5672);
                    if (host.SslEnabled)
                    {
                        r_host.Ssl.Enabled = true;
                        //r_host.Ssl.ServerName = host.Host;
                        r_host.Ssl.AcceptablePolicyErrors = System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors | System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable | System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch;
                    }
                    rabbit_conn.Hosts = new[] { r_host };

                    new LogRecord()
                    {
                        Source  = _Name,
                        HostId  = host.Host_Id,
                        Message = String.Format("Подключаемся к {0}серверу RabbitMQ...", host.SslEnabled ? "SSL " : ""),
                        Details = host.ConnectionString
                    }
                    .TryWrite(SQLconn, dbLog);

                    IEasyNetQLogger r_Log = new EasyNetQ.Loggers.NullLogger();
                    if (DebugFlag.Enabled)
                    {
                        try {
                            r_Log = new RabbitTextLogger(new StreamWriter(Path.Combine(Path.GetTempPath(), Exchange_Svc.MyServiceName, String.Format("rabbit_{0}.log", host.Host_Id)))
                            {
                                AutoFlush = true
                            });
                            //r_Log = new EasyNetQ.Loggers.ConsoleLogger();
                        } catch (Exception ex) {
                            Trace.TraceWarning("{4}\t{0}: не удалось создать журнал rabbit_{1} ({2}): {3}", _Name, host.Host_Id, host.ConnectionString, ex.Message, DateTime.Now);
                        }
                    }

                    try {
                        rabbit_conn.Validate();
                        var bus = RabbitHutch.CreateBus(rabbit_conn, services => services.Register <IEasyNetQLogger>(logger => r_Log));
                        Buses.Add(bus);
                        foreach (var q in RabbitQueues.Where(q => q.Host_Id == host.Host_Id))
                        {
                            q.Bus = bus;
                        }

                        for (int i = 0; i < 10; i++)
                        {
                            if (bus.IsConnected)
                            {
                                new LogRecord()
                                {
                                    Source  = _Name,
                                    HostId  = host.Host_Id,
                                    Message = String.Format("Установлено {0}подключение к RabbitMQ", host.SslEnabled ? "SSL " : ""),
                                    Details = host.ConnectionString
                                }
                                .TryWrite(SQLconn, dbLog);

                                break;
                            }
                            Thread.Sleep(10);
                        }
                    } catch (Exception ex) {
                        new LogRecord()
                        {
                            Source  = _Name,
                            IsError = true,
                            Message = String.Format("Ошибка при {0}подключении к серверу RabbitMQ: {1}", host.SslEnabled ? "SSL " : "", ex.Message),
                            Details = rabbit_conn.ToString()
                        }
                        .TryWrite(SQLconn, dbLog);
                    }
//					}
                }

                if (Buses.Count == 0)
                {
                    var msg = "Не удалось подключиться ни к одному из хостов RabbitMQ. Остановка службы";
                    new LogRecord()
                    {
                        Source  = _Name,
                        IsError = true,
                        Message = msg
                    }
                    .TryWrite(SQLconn, dbLog);
                    FailStart(msg);
                }

                // Запускаем обработчики очередей
                workers = new List <Worker>();
                foreach (var queue in RabbitQueues.Where(q => q.Bus != null))
                {
                    Worker w;

                    if (queue.Direction.Trim() == "In")
                    {
                        w = new Receiver(dbConnStr, (IBus)queue.Bus, queue);
                    }
                    else if (queue.Direction.Trim() == "Out")
                    {
                        w = new Sender(dbConnStr, (IBus)queue.Bus, queue);
                    }
                    else
                    {
                        new LogRecord()
                        {
                            Source  = _Name,
                            HostId  = queue.Host.Host_Id,
                            QueueId = queue.Queue_Id,
                            IsError = true,
                            Message = String.Format("Неизвестный тип очереди: '{0}'", queue.Direction),
                            Details = queue.Name
                        }
                        .TryWrite(SQLconn, dbLog);

                        continue;
                    }

                    new LogRecord()
                    {
                        Source  = _Name,
                        HostId  = queue.Host.Host_Id,
                        QueueId = queue.Queue_Id,
                        Message = "Запускаем обработчик очереди сообщений...",
                        Details = w.QueueFullName
                    }
                    .TryWrite(SQLconn, dbLog);

                    w.Run();
                    workers.Add(w);
                }

                timer           = new System.Timers.Timer(30000D);
                timer.AutoReset = true;
                timer.Elapsed  += timer_Elapsed;
                timer.Start();

                                #if DEBUG
                while (!workers.All(w => w.Thread.Join(3000)))
                {
                    continue;
                }
                                #endif
            }
        }
Example #5
0
        public override void Start()
        {
            var aBus = Bus.Advanced;

            if (DebugFlag.Enabled)
            {
                try {
                    dbLog = new StreamWriter(Path.Combine(Path.GetTempPath(), Exchange_Svc.MyServiceName, String.Format("{0}.dblog", _Name)))
                    {
                        AutoFlush = true
                    };
                } catch (Exception ex) {
                    Trace.TraceWarning("{2}\t{0}: не удалось создать журнал dblog: {1}", _Name, ex.Message, DateTime.Now);
                }
            }

            new LogRecord()
            {
                Source  = this._Name,
                HostId  = this.HostId,
                QueueId = this.QueueId,
                Message = "Обработчик отправки сообщений запущен",
                Details = QueueFullName
            }
            .TryWrite(dbConnStr, dbLog);

            int  MsgCounter          = 0;
            int  TotalMsgCounter     = 0;
            long BytesProcessed      = 0;
            long TotalBytesProcessed = 0;

            while (!ShouldStop)
            {
                using (var exdb = new exDb(dbConnStr)) {
                    exdb.Log = dbLog;
                    Outbound message;

                    while (!ShouldStop && aBus.IsConnected &&
                           null != (message = exdb.Outbound.FirstOrDefault(o => o.QueueId == this.QueueId && o.DateSent == null)))
                    {
                        new LogRecord()
                        {
                            Source      = this._Name,
                            HostId      = this.HostId,
                            QueueId     = this.QueueId,
                            Outbound_Id = message.Message_Id,
                            Message     = "Начинаем отправку сообщения...",
                            Details     = String.Format("{0} символов", message.Message.Length)
                        }
                        .TryWrite(exdb);

                        byte[] data;
                        //TODO: every xx (1000?) messages do gc.collect(2) to clear LOH
                        try {
                            data = Queue.Base64Data ? Convert.FromBase64String(message.Message)
                                                                : Encoding.UTF8.GetBytes(message.Message);

                            BytesProcessed      += sizeof(byte) * data.Length;
                            TotalBytesProcessed += sizeof(byte) * data.Length;
                            MsgCounter++;
                            TotalMsgCounter++;
                        } catch (Exception ex) {
                            new LogRecord()
                            {
                                Source      = this._Name,
                                HostId      = this.HostId,
                                QueueId     = this.QueueId,
                                Outbound_Id = message.Message_Id,
                                IsError     = true,
                                Message     = "Ошибка декодирования base64",
                                Details     = ex.Message
                            }
                            .TryWrite(exdb);

                            message.ErrorFlag = true;
                            message.DateSent  = new DateTime(1900, 1, 1);
                            exdb.TrySubmitChanges();
                            continue;
                        }

                        if (IntPtr.Size == 4 && BytesProcessed > 3 * (1024 * 1024 * 512))
                        {
                            LogInfo(exdb, "Forcing GC.Collect(2)",
                                    String.Format("Processed {0} messages, {1} MB since last GC. Total {2} messages, {3} MB. Reported GC UsedMem {4} MB"
                                                  , MsgCounter, BytesProcessed / (1024 * 1024), TotalMsgCounter, TotalBytesProcessed / (1024 * 1024), GC.GetTotalMemory(false) / (1024 * 1024)));

//							new LogRecord() {
//								Source = this._Name,
//								HostId = this.HostId,
//								QueueId = this.QueueId,
//								Message = "Forcing GC.Collect(2)",
//								Details = String.Format("Processed {0} messages, {1} MB since last GC ({2} msgs, {3} MB total). Reported GC UsedMem {4} MB"
//								                        ,MsgCounter, BytesProcessed/(1024*1024), TotalMsgCounter, TotalBytesProcessed/(1024*1024), GC.GetTotalMemory(false)/(1024*1024)) }
//							.TryWrite(exdb);

                            GC.Collect(2);

                            MsgCounter     = 0;
                            BytesProcessed = 0;

                            LogInfo(exdb, "Finished GC.Collect(2)",
                                    String.Format("Reported GC UsedMem  {0} MB", GC.GetTotalMemory(false) / (1024 * 1024)));

//							new LogRecord() {
//								Source = this._Name,
//								HostId = this.HostId,
//								QueueId = this.QueueId,
//								Message = "Finished GC.Collect(2)",
//								Details = String.Format("Reported GC UsedMem  {0} MB", GC.GetTotalMemory(false)/(1024*1024)) }
//							.TryWrite(exdb);
                        }

                        new LogRecord()
                        {
                            Source      = this._Name,
                            HostId      = this.HostId,
                            QueueId     = this.QueueId,
                            Outbound_Id = message.Message_Id,
                            Message     = Queue.Base64Data ? "Декодировали base64" : "Сформировали массив байт",
                            Details     = String.Format("{0} байт", data.Length)
                        }
                        .TryWrite(exdb);

                        try {
                            var mp = new MessageProperties();
                            if (!String.IsNullOrWhiteSpace(message.AppMsgId))
                            {
                                mp.MessageId = message.AppMsgId;
                            }

                            IExchange ex = String.IsNullOrWhiteSpace(this.ExchangeName) ? Exchange.GetDefault() :
                                           new Exchange(this.ExchangeName);

                            aBus.Publish(ex, this.QueueName, true, false, mp, data);
                        } catch (Exception ex) {
                            new LogRecord()
                            {
                                Source      = this._Name,
                                HostId      = this.HostId,
                                QueueId     = this.QueueId,
                                Outbound_Id = message.Message_Id,
                                IsError     = true,
                                Message     = "Ошибка при отправке сообщения",
                                Details     = ex.Message
                            }
                            .TryWrite(exdb);
                            Thread.Sleep(PollInterval);

                            continue;
                        }

                        new LogRecord()
                        {
                            Source      = this._Name,
                            HostId      = this.HostId,
                            QueueId     = this.QueueId,
                            Outbound_Id = message.Message_Id,
                            Message     = "Сообщение успешно отправлено!",
                            Details     = this.QueueFullName
                        }
                        .TryWrite(exdb);

                        message.DateSent = DateTime.Now;
                        exdb.TrySubmitChanges();
                    }
                }

                Thread.Sleep(PollInterval);
            }

            // Вышли из главного цикла (ShouldStop = true)
            new LogRecord()
            {
                Source  = this._Name,
                HostId  = this.HostId,
                QueueId = this.QueueId,
                Message = "Получена команда остановить обработчик. Нормальное завершение работы",
                Details = QueueFullName
            }
            .TryWrite(dbConnStr, dbLog);
        }
Example #6
0
 public void LogError(exDb dbContext, string _Message, string _Details, int?msg_Id = null)
 {
     WriteLogMessage(dbContext, null, msg_Id, true, _Message, _Details);
 }
Example #7
0
 public void LogInfo(exDb dbContext, string _Message, string _Details, int?msg_Id = null)
 {
     WriteLogMessage(dbContext, null, msg_Id, false, _Message, _Details);
 }