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); } }
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); } }