private void HeatbeatRun() { while (!cancelSource.IsCancellationRequested) { try { foreach (var context in Contexts.CopyToList()) { ProducterBLL bll = new ProducterBLL(); SqlHelper.ExcuteSql(context.ProducterProvider.Config.ManageConnectString, (c) => { context.ManageServerTime = c.GetServerDate();//重新校准时间 bll.ProducterHeartbeat(c, context.ProducterInfo.ProducterModel.tempid, context.ProducterInfo.ProducterModel.mqpathid); }); CheckMqPathUpdate(context); } } catch (Exception exp) { ErrorLogHelper.WriteLine(-1, "", "HeatbeatRun", "生产者心跳循环错误", exp); } System.Threading.Thread.Sleep(SystemParamConfig.Producter_HeatBeat_Every_Time * 1000); DebugHelper.WriteLine(-1, "", "HeatbeatRun", "生产者心跳循环一轮结束"); } }
public void Open() { try { DebugHelper.WriteLine(-1, MQPath, "Open", "生产者开始初始化"); //初始化上下文信息 ProducterBLL bll = new ProducterBLL(); SqlHelper.ExcuteSql(Config.ManageConnectString, (c) => { Context.ProducterInfo = bll.GetProducterInfo(c, MQPath, ProducterName); Context.ProducterInfo.LoadBalance = LoadBalance; Context.ManageServerTime = c.GetServerDate(); }); Context.IsNeedReload = false; Context.LastMQPathUpdateTime = Context.ProducterInfo.MqPathModel.lastupdatetime; //获取系统配置信息 ConfigHelper.LoadConfig(Config.ManageConnectString); NetCommand = new RedisNetCommand(ConfigHelper.RedisServer); ProducterHeartbeatProtect.Instance(Context).Contexts.Add(Context);//注册上下文 DebugHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Open", "生产者初始化成功"); LogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Open", "生产者初始化成功"); } catch (Exception exp) { ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Open", "生产者初始化", exp); throw exp; } }
/// <summary> /// 资源释放 /// </summary> public void Dispose() { try { ProducterBLL bll = new ProducterBLL(); SqlHelper.ExcuteSql(Config.ManageConnectString, (c) => { bll.RemoveProducter(c, Context.ProducterInfo.ProducterModel.tempid, Context.ProducterInfo.MqPathModel.id); }); DebugHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者移除注册信息成功"); LogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者移除注册信息成功"); } catch (Exception exp) { ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者移除注册信息出错", exp); } try { DebugHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者资源开始释放"); ProducterHeartbeatProtect.Instance(Context).Contexts.Remove(Context); //移除上下文 Context.Dispose(); //释放上下文 DebugHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者资源释放成功"); LogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者资源释放成功"); } catch (Exception exp) { ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "Dispose", "生产者资源释放出错", exp); throw exp; } }
private void CheckMqPathUpdate(ProducterContext context) { lock (_contextupdatelock) { string mqpath = ""; try { if (context.Disposeing == true) { return; } mqpath = context.ProducterInfo.MqPathModel.mqpath; //检查当前队列是否有更新,有更新则重启producter var lastupdatetime = GetLastUpdateTimeOfMqPath(context); if (context.LastMQPathUpdateTime < lastupdatetime || context.IsNeedReload) { ProducterBLL bll = new ProducterBLL(); ProducterInfo productinfo = null; SqlHelper.ExcuteSql(context.ProducterProvider.Config.ManageConnectString, (c) => { productinfo = bll.GetProducterInfo(c, context.ProducterProvider.MQPath, context.ProducterProvider.ProducterName); }); context.ProducterInfo.Update(productinfo); context.IsNeedReload = false; context.LastMQPathUpdateTime = lastupdatetime; redislistener.RedisServerIp = ConfigHelper.RedisServer; } //检查发送错误,错误发生超过一分钟自动重启来解决错误状态 if (context.SendMessageErrorTime != null && (DateTime.Now - context.SendMessageErrorTime) > TimeSpan.FromSeconds(SystemParamConfig.Producter_SendError_Clear_Time)) { context.IsNeedReload = true; context.SendMessageErrorTime = null; } } catch (Exception exp) { ErrorLogHelper.WriteLine(context.GetMQPathID(), context.GetMQPath(), "CheckMqPathUpdate", "生产者检测队列是否更新错误", exp); } } }
/// <summary> /// 发送消息 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="objmsg"></param> public void SendMessage <T>(T objmsg) { try { var json = ""; ProducterTimeWatchInfo.JsonHelperSerializer += Log.TimeWatchLog.Debug(() => { if (!(objmsg is string)) { json = new Serialization.JsonHelper().Serializer(objmsg); } else { json = objmsg as string; } }); //发送消息有n次重试机会 int errortrycount = 0; while (errortrycount < Context.ProducterInfo.LoadBalance.SendMessageErrorTryAgainCount) { LoadBalanceNodeInfo loadbalancenodeinfo = null; ProducterTimeWatchInfo.GetLoadBalanceNodeInfo += Log.TimeWatchLog.Debug(() => { loadbalancenodeinfo = Context.ProducterInfo.GetLoadBalanceNodeInfo(); }); if (loadbalancenodeinfo == null) { throw new BusinessMQException(string.Format("无法获取队列{0}的可用的负载均衡数据节点", MQPath)); } string datanodeconnectstring = new ProducterBLL().GetDataNodeConnectString(SystemParamConfig.Producter_DataNode_ConnectString_Template_ToSendMessage, loadbalancenodeinfo.DataNodeModel); var partitionidinfo = PartitionRuleHelper.GetPartitionIDInfo(loadbalancenodeinfo.MQPathPartitionModel.partitionid); var manageservertime = Context.ManageServerTime;//.AddSeconds(1);发送消息要比标准时间提前1s,这样消息分表可以提前1s string tablename = PartitionRuleHelper.GetTableName(partitionidinfo.TablePartition, manageservertime); try { ProducterTimeWatchInfo.SendMessage += Log.TimeWatchLog.Debug(() => { double inserttime = 0; double allinserttime = Log.TimeWatchLog.Debug(() => { inserttime = Log.TimeWatchLog.Debug(() => { tb_messagequeue_dal dal = new tb_messagequeue_dal(); dal.TableName = tablename; SqlHelper.ExcuteSql(datanodeconnectstring, (c) => { dal.Add2(c, new tb_messagequeue_model() { message = json, mqcreatetime = DateTime.Now, sqlcreatetime = manageservertime , source = (int)EnumMessageSource.Common, state = (int)EnumMessageState.CanRead }); }); }); }); //ProducterTimeWatchTest.AddMessages(string.Format("总插入消息:{0}s,插入消息:{1}s",allinserttime,inserttime)); }); NetCommand.SendMessage(mqpath); return; } catch (SqlException exp) { ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "SendMessage", string.Format("发送消息出现节点错误,节点:{0}", loadbalancenodeinfo.DataNodeModel.datanodepartition), exp); Context.ProducterInfo.RemoveMQPathPartition(loadbalancenodeinfo.DataNodeModel.datanodepartition);//数据层出错视为数据节点异常,则移除。将在一定时间内尝试恢复 Context.ProducterInfo.LoadBalance.AddError(new ErrorLoadBalancePartitionInfo() { PartitionId = loadbalancenodeinfo.MQPathPartitionModel.partitionid, PartitionIndex = loadbalancenodeinfo.MQPathPartitionModel.partitionindex }); //Context.IsNeedReload = true; if (Context.SendMessageErrorTime == null) { Context.SendMessageErrorTime = DateTime.Now; } } errortrycount++; } throw new BusinessMQException(string.Format("发送消息出现系统级错误,并超过重试次数,请检查。队列:{0}", MQPath)); } catch (Exception exp) { ErrorLogHelper.WriteLine(Context.GetMQPathID(), Context.GetMQPath(), "SendMessage", "生产者发送消息出错", exp); throw exp; } }