public ActionResult ClearNotOnLineByClientID(int id, int mqpathid)
        {
            try
            {
                using (DbConn conn = DbConfig.CreateConn(DataConfig.MqManage))
                {
                    try
                    {
                        conn.Open();
                        conn.BeginTransaction();
                        var item = new tb_consumer_partition_dal().Get(conn, id);
                        new tb_consumer_dal().DeleteNotOnLineByClientID(conn, item.consumerclientid, 20);

                        conn.Commit();
                    }
                    catch (Exception exp)
                    {
                        conn.Rollback();
                        throw exp;
                    }

                    return(Json(new { code = 1, msg = "清理完毕" }));
                }
            }
            catch (Exception e)
            {
                return(Json(new { code = -1, msg = e.Message }));
            }
        }
 public ActionResult UpdateLastMqID(int id, string mqpathid)
 {
     using (DbConn conn = DbConfig.CreateConn(DataConfig.MqManage))
     {
         conn.Open();
         var o = new tb_consumer_partition_dal().Get(conn, id);
         ViewBag.id       = id;
         ViewBag.lastmqid = o.lastmqid; ViewBag.mqpathid = mqpathid;
     }
     return(View());
 }
        /// <summary>
        /// 标记消息为已消费
        /// </summary>
        public void MarkFinished()
        {
            int consumerclientid = 0; int partitionid = 0; long mqid = 0;

            try
            {
                var mqidinfo = PartitionRuleHelper.GetMQIDInfo(Model.id); partitionid = PartitionRuleHelper.GetPartitionID(new PartitionIDInfo()
                {
                    DataNodePartition = mqidinfo.DataNodePartition, TablePartition = mqidinfo.TablePartition
                });
                tb_consumer_partition_dal dal = new tb_consumer_partition_dal();
                int result = 0; consumerclientid = Context.ConsumerInfo.ConsumerClientModel.id; mqid = this.Model.id;
                //尝试标记消息已消费
                bool isupdatesuccess = false; int tryerrorcount = 0;
                while (isupdatesuccess == false)
                {
                    try
                    {
                        SqlHelper.ExcuteSql(Context.ConsumerProvider.Config.ManageConnectString, (c) =>
                        {
                            result = dal.UpdateLastMQID(c, consumerclientid, partitionid, mqid);
                        });
                        isupdatesuccess = true;
                    }
                    catch (Exception exp)
                    {
                        tryerrorcount++;
                        if (tryerrorcount <= SystemParamConfig.Consumer_TrySetMessageRead_FailCount)
                        {
                            System.Threading.Thread.Sleep((int)(SystemParamConfig.Consumer_TrySetMessageRead_ErrorSleepTime * 1000));
                            Log.ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "MarkFinished", string.Format("标记消息'已完成'出错,尝试第{0}次", tryerrorcount + ""), exp);
                        }
                        else
                        {
                            throw new BusinessMQException(string.Format("标记消息'已完成'出错,放弃第{0}次重试!", tryerrorcount + ""), exp);
                        }
                    }
                }
                if (result != 1)
                {
                    throw new BusinessMQException(string.Format("当前消息消费完成后更新失败,可能是系统级消息乱序消费导致。consumerclientid:{0},partitionid:{1},mqid:{2}",
                                                                Context.ConsumerInfo.ConsumerClientModel.id, partitionid, this.Model.id));
                }
                //消费者端标记为已消费
                _isMarkFinished = true;
            }
            catch (Exception exp)
            {
                throw new BusinessMQException(string.Format("当前消息消费标记“已完成”时出错,consumerclientid:{0},partitionid:{1},mqid:{2}", consumerclientid, partitionid, mqid), exp);
            }
        }
Beispiel #4
0
        public tb_consumer_partition_model RegisterConsumerPartition(DbConn PubConn, int clientid, int partitionindex, string mqpath, long tempid)
        {
            var mqpathmodel = GetMQPath(PubConn, mqpath);
            tb_mqpath_partition_dal mqpathpartitiondal = new tb_mqpath_partition_dal();
            var mqpathpartitionmodel = mqpathpartitiondal.GetOfConsumer(PubConn, partitionindex, mqpathmodel.id);

            if (mqpathpartitionmodel == null)
            {
                return(null);
            }
            tb_consumer_partition_dal dal = new tb_consumer_partition_dal();

            if (dal.Edit2(PubConn, new tb_consumer_partition_model()
            {
                consumerclientid = clientid, lastconsumertempid = tempid, partitionid = mqpathpartitionmodel.partitionid, partitionindex = partitionindex
            }) <= 0)
            {
                var  partitionidinfo = PartitionRuleHelper.GetPartitionIDInfo(mqpathpartitionmodel.partitionid); var datanodename = PartitionRuleHelper.GetDataNodeName(partitionidinfo.DataNodePartition);
                long maxid = -1; DateTime serverdate = PubConn.GetServerDate(); string tablename = PartitionRuleHelper.GetTableName(partitionidinfo.TablePartition, serverdate);
                SqlHelper.ExcuteSql(this.GetDataNodeConnectString(PubConn, partitionidinfo.DataNodePartition), (c) => {
                    var exist = c.TableIsExist(tablename); if (!exist)
                    {
                        throw new BusinessMQException(string.Format("当前数据节点{0},表{1}不存在", partitionidinfo.DataNodePartition, tablename));
                    }
                    tb_messagequeue_dal mqdal = new tb_messagequeue_dal(); mqdal.TableName = tablename;
                    maxid = mqdal.GetMaxId(c);
                    if (maxid <= 0)
                    {
                        maxid = PartitionRuleHelper.GetMQID(new MQIDInfo()
                        {
                            AutoID = 0, DataNodePartition = partitionidinfo.DataNodePartition, Day = serverdate, TablePartition = partitionidinfo.TablePartition
                        });
                    }
                });
                dal.Add2(PubConn, new tb_consumer_partition_model()
                {
                    consumerclientid = clientid, lastconsumertempid = tempid, lastmqid = maxid, partitionid = mqpathpartitionmodel.partitionid, partitionindex = partitionindex
                });
            }
            return(dal.Get(PubConn, clientid, mqpathpartitionmodel.partitionid));
        }
        public ActionResult Delete(int id, int mqpathid)
        {
            try
            {
                using (DbConn conn = DbConfig.CreateConn(DataConfig.MqManage))
                {
                    try
                    {
                        conn.Open();
                        conn.BeginTransaction();

                        var item = new tb_consumer_partition_dal().Get(conn, id);
                        new tb_consumer_dal().DeleteNotOnLineByClientID(conn, item.consumerclientid, 20);
                        var consumer = new tb_consumer_dal().GetByTempId(conn, item.lastconsumertempid);
                        if (consumer != null && consumer.tempid == 0)
                        {
                            throw new Exception("当前消费者未处于正常离线状态,若是非正常断线状态,可以在20s超时后尝试");
                        }
                        new tb_consumer_partition_dal().Delete(conn, id);
                        conn.Commit();
                    }
                    catch (Exception exp)
                    {
                        conn.Rollback();
                        throw exp;
                    }
                }
                this.SendCommandToRedistReStart(mqpathid, XXF.BaseService.MessageQuque.BusinessMQ.SystemRuntime.EnumCommandReceiver.Consumer);
                return(Json(new { code = 1, msg = "删除成功" }));
            }

            catch (Exception e)
            {
                return(Json(new { code = -1, msg = e.Message }));
            }
        }
        /// <summary>
        /// 任务调度平台根据发布的任务时间配置,定时回调运行方法
        /// 开发人员的任务插件必须要重载并该方法
        /// </summary>
        public override void Run()
        {
            runcount++;

            ConfigHelper.LoadConfig(this.AppConfig["BusinessMQManageConnectString"]);

            List <tb_partition_model>           userdpartitions          = new List <tb_partition_model>();
            Dictionary <int, tb_datanode_model> datanodemodels           = new Dictionary <int, tb_datanode_model>();
            List <RegisterdConsumersModel>      registeredconsumermodels = new List <RegisterdConsumersModel>();
            List <tb_consumer_model>            consumers = new List <tb_consumer_model>();
            DateTime servertime = DateTime.Now;

            SqlHelper.ExcuteSql(this.AppConfig["BusinessMQManageConnectString"], (c) =>
            {
                tb_partition_dal partitiondal = new tb_partition_dal();
                userdpartitions             = partitiondal.List(c, true);
                tb_datanode_dal datanodedal = new tb_datanode_dal();
                var ms = datanodedal.List(c);
                foreach (var m in ms)
                {
                    datanodemodels.Add(m.datanodepartition, m);
                }
                servertime = c.GetServerDate();

                //获取当前注册的消费者
                tb_consumer_dal consumerdal = new tb_consumer_dal();
                registeredconsumermodels    = consumerdal.GetRegisterdConsumers(c);
                consumers = consumerdal.GetAllList(c);
            });
            //消费者端心跳停止,异常退出检测(超过1分钟)
            List <Exception> exps = new List <Exception>();

            foreach (var c in consumers)
            {
                if ((servertime - c.lastheartbeat) > TimeSpan.FromMinutes(1))
                {
                    exps.Add(new Exception(string.Format("当前消费者tempid:{0},consumerclientid:{1}", c.tempid, c.consumerclientid)));
                }
            }
            Error(this.AppConfig["BusinessMQManageConnectString"], "消费者端心跳停止,异常退出检测(超过1分钟),若是异常停止,请手工清除消费者中断", exps);
            //消费者端长时间无消费,但是还有多余消息(超过10分钟未消费,但还有多余消息未消费)
            exps.Clear();
            foreach (var c in registeredconsumermodels)
            {
                if ((servertime - c.consumerpartitionmodel.lastupdatetime) > TimeSpan.FromMinutes(10))
                {
                    var partitionidinfo = XXF.BaseService.MessageQuque.BusinessMQ.SystemRuntime.PartitionRuleHelper.GetPartitionIDInfo(c.consumerpartitionmodel.partitionid);
                    var tablename       = XXF.BaseService.MessageQuque.BusinessMQ.SystemRuntime.PartitionRuleHelper.GetTableName(partitionidinfo.TablePartition, servertime.Date);
                    SqlHelper.ExcuteSql(this.GetDataNodeConnectString(datanodemodels[partitionidinfo.DataNodePartition]), (conn) =>
                    {
                        tb_messagequeue_dal messagedal = new tb_messagequeue_dal(); messagedal.TableName = tablename;
                        long maxmqid = messagedal.GetMaxID(conn);
                        if (maxmqid > c.consumerpartitionmodel.lastmqid && (servertime - messagedal.GetIDCreateTime(conn, maxmqid).Value > TimeSpan.FromMinutes(10)))//还有消息未消费,且该消息的创建时间是10分钟前
                        {
                            exps.Add(new Exception(string.Format("当前消费者tempid:{0},consumerclientid:{1},client:{2},clientname:{3}", c.consumermodel.tempid,
                                                                 c.consumermodel.consumerclientid, c.consumerclientmodel.client, c.consumermodel.clientname)));
                        }
                    });
                }
            }
            Error(this.AppConfig["BusinessMQManageConnectString"], "消费者端长时间无消费,但是还有多余消息(超过已创建超过10分钟的消息未消费),可能是消费者处理逻辑异常", exps);
            //某个分区没有指定消费者(分区没有消费信息,或者分区消费最后消费时间超过1个小时无消费)
            exps.Clear();
            if (runcount % (12 * 6) == 0)
            {
                foreach (var u in userdpartitions)
                {
                    bool isfind = false;
                    foreach (var c in registeredconsumermodels)
                    {
                        if (c.consumerpartitionmodel.partitionid == u.partitionid)
                        {
                            isfind = true; break;
                        }
                    }
                    if (isfind == false)
                    {
                        SqlHelper.ExcuteSql(this.AppConfig["BusinessMQManageConnectString"], (c) =>
                        {
                            tb_consumer_partition_dal dal = new tb_consumer_partition_dal();
                            var model = dal.GetByPartitionId(c, u.partitionid);
                            if (model == null)
                            {
                                exps.Add(new Exception(string.Format("分区{0}未指定消费者", u.partitionid)));
                            }
                            //else if((servertime - model.lastupdatetime) > TimeSpan.FromHours(24))
                            //     exps.Add(new Exception(string.Format("分区{0}消费者已注销,且有1天未消费", u.partitionid)));
                        });
                    }
                }
                Error(this.AppConfig["BusinessMQManageConnectString"], "某个分区没有指定消费者(分区没有消费信息)", exps);
            }
        }