/// <summary> /// 获取生产者实例并启动它,它和生产者服务类实例不是一个东西,请勿混淆 /// </summary> /// <returns></returns> protected IONSProducer GetProducer() { IONSProducer producer = ONSHelper.ONSProducerList.Where(p => (p.Type == this.MessageType.ToString().ToUpper()) && (p.ProducerId == this.Pid)).FirstOrDefault(); if (producer == null) { //生产者对象不存在,则新建 lock (_lockHelper) { producer = ONSHelper.ONSProducerList.Where(p => (p.Type == this.MessageType.ToString().ToUpper()) && (p.ProducerId == this.Pid)).FirstOrDefault(); if (producer == null) { ONSFactoryProperty onsProducerFactoryProperty = new ONSFactoryProperty(); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.AccessKey, _AliyunOnsAccessKey); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.SecretKey, _AliyunOnsSecretKey); //用老的.net SDK按最新的RocketMQ架构,引入GroupId代替ProducerId和ConsumerId onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.ProducerId, this.Pid); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.PublishTopics, this.Topic); producer = InitilizeProducer(onsProducerFactoryProperty); ONSHelper.ONSProducerList.Add(producer); producer.start(); } } } return(producer); }
/// <summary> /// 上游生产者的实现rocketmq的核心方法,其中会由rocketmq自动间接调用AbstractProducerService实例的InternalProduce方法 /// </summary> /// <param name="model">接收的参数</param> /// <returns>事务执行结果</returns> public bool Process(T model) { if (_AliyunOnsIsAllowedToSend != "1") { return(false); } string requestTraceId = ""; string key = this.CreateMessageKey(); string failureReason = ""; string body = ""; bool accomplishment = false; int producedTimes = 0; int errorTimes = 0; try { //获取requestTraceId requestTraceId = this.GetRequestTraceId(); //此方法中,只要是普通消息或顺序消息都是空实现,直接返回true InternalProcess(model); //序列化实体,即消息正文 body = model.GetType().Name.ToLower() == "system.string" ? model.ToString() : JsonConvert.SerializeObject(model); //防止中文乱码 body = Base64Util.Encode(body); //获取生产者 IONSProducer producer = GetProducer(); //生成消息实体 Message message = new Message(this.Topic, this.Tag, body); message.setKey(key); message.putUserProperties("type", this.MessageType.ToString()); message.putUserProperties("requestTraceId", requestTraceId); //message.putUserProperties("shardingKey", shardingKey); //定义消息结果对象 SendResultONS sendResultONS = null; //尝试发送 sendResultONS = TryToSend(producer, message, null, key, errorTimes); //判断结果,一般走不到这步,因为如果发送有问题会直接抛出异常的 if (sendResultONS == null) { throw new Exception("发送BASE消息失败。key=" + key); } //更新发送状态 accomplishment = true; //更新消费次数 producedTimes = 1; } catch (Exception e) { //将内部捕捉的错误赋值给failureReason,然后由ProduceData的FailureReason属性统一处理 failureReason = "发送BASE消息,key=" + key + ",捕捉异常:" + e.ToString(); return(false); } finally { //无论是否有异常都统一写入生产日志 LogData(key, body, "", "", failureReason, accomplishment, producedTimes, failureReason != "" ? false : true); } return(true); }
/// <summary> /// 尝试发送消息 /// </summary> /// <param name="producer">生产者实例</param> /// <param name="message">消息实例</param> /// <param name="parameter">发送所需参数</param> /// <param name="key">消息的唯一标识</param> /// <param name="errorTimes">本系统自己自己执行时发现出错后,记录的错误次数(此参数不适用于生产次数)</param> /// <returns></returns> protected SendResultONS TryToSend(IONSProducer producer, Message message, object parameter, string key, int errorTimes) { SendResultONS sendResultONS = null; try { sendResultONS = producer.send(message, parameter); } catch (Exception e) { //错误计数累加 errorTimes++; //无论是阿里云服务不可用,还是生产者挂了,一共3次机会,即执行1次,然后最多重试两次 if (errorTimes < 3) { //如果生产者挂了 if (e.ToString().IndexOf("Your producer has been shutdown.") >= 0) { //置空producer producer = null; //重新获取producer并启动 producer = GetProducer(); //等待3秒 System.Threading.Thread.Sleep(3000); } else { //如果是阿里云服务不可用,等待1秒 System.Threading.Thread.Sleep(1000); } //递归 sendResultONS = TryToSend(producer, message, parameter, key, errorTimes); } else { //重试2次都还是失败 string className = this.GetType().Name; string methodName = "Process"; string errorMessage = _Environment + "." + _ApplicationAlias + "." + className + "." + methodName + "尝试发送时,出现了第" + errorTimes + "次出错,key=" + key + ":" + e.ToString(); //记录本地错误日志 DebugUtil.Debug(errorMessage); //记录FATAL日志 ONSHelper.SaveLog(LogTypeEnum.FATAL, className, methodName, errorMessage); //发送邮件 ONSHelper.SendDebugMail(_Environment + "." + _ApplicationAlias + "." + className + "." + methodName + "尝试发送时出错", errorMessage); //抛出异常 throw new Exception(errorMessage); } } return(sendResultONS); }
/// <summary> /// 创建生产者实例 /// </summary> /// <typeparam name="T">生产者服务基类类型</typeparam> /// <param name="assembly">生产者服务类所在程序集</param> /// <param name="type">生产者服务类的类型</param> /// <param name="messageType">消息类型BASE,ORDER,TRAN</param> /// <param name="func">生成生产者实例的委托代码</param> internal static void CreateProducer <T>(Assembly assembly, Type type, ONSMessageType messageType, Func <ONSFactoryProperty, string, string, IONSProducer> func) { if (type.BaseType.FullName.IndexOf(typeof(T).Name) >= 0) { //添加到生产者服务类实例列表 //ONSProducerServiceList.Add(type); object service = assembly.CreateInstance(type.FullName); ONSProducerServiceList.Add(service); //获取服务接口 IAbstractProducerService iservice = (IAbstractProducerService)service; //获取枚举对象 Enum topicTag = iservice.TopicTag; if (topicTag != null) { string serviceTopic = topicTag.GetType().Name; string topic = (_Environment + "_" + serviceTopic).ToUpper(); //string producerId = ("PID_" + topic).ToUpper(); string producerId = ("GID_" + topic).ToUpper(); IONSProducer producer = ONSProducerList.Where(p => (p.Type == messageType.ToString()) && (p.ProducerId == producerId)).FirstOrDefault(); if (producer == null) { //实例化ONSFactoryProperty ONSFactoryProperty onsProducerFactoryProperty = new ONSFactoryProperty(); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.AccessKey, _AliyunOnsAccessKey); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.SecretKey, _AliyunOnsSecretKey); //用老的.net SDK按最新的RocketMQ架构,引入GroupId代替ProducerId和ConsumerId onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.ProducerId, producerId); onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.PublishTopics, topic); if (_AliyunOnsProducerLogPath != "") { if (Directory.Exists(_AliyunOnsProducerLogPath)) { onsProducerFactoryProperty.setFactoryProperty(ONSFactoryProperty.LogPath, _AliyunOnsProducerLogPath); } } //获取生产者IONSProducer producer = func(onsProducerFactoryProperty, topic, producerId); //记录生产者初始化信息 DebugUtil.Debug("Topic:" + topic + ",ProducerId(" + producer.Type.ToString() + "):" + producer.ProducerId + "生产者new()"); //新增代理类ONSProducer实例到ONSProducerList中 ONSProducerList.Add(producer); } } } }
/// <summary> /// 上游生产者的实现rocketmq的核心方法,其中会由rocketmq自动间接调用AbstractTransactionProducerService实例的InternalProduce方法 /// </summary> /// <param name="model">接收的参数</param> /// <returns>事务执行结果</returns> public bool Process(T model) { if (_AliyunOnsIsAllowedToSend != "1") { return(false); } string requestTraceId = ""; string key = this.CreateMessageKey(); string failureReason = ""; string body = ""; bool accomplishment = false; int producedTimes = 0; int errorTimes = 0; try { //获取requestTraceId requestTraceId = this.GetRequestTraceId(); //序列化实体,即消息正文 body = model.GetType().Name.ToLower() == "system.string" ? model.ToString() : JsonConvert.SerializeObject(model); //防止中文乱码 body = Base64Util.Encode(body); //获取生产者 IONSProducer producer = GetProducer(); //Message实体的body不能为空 Message message = new Message(this.Topic, this.Tag, body); message.setKey(key); message.putUserProperties("type", this.MessageType.ToString()); message.putUserProperties("requestTraceId", requestTraceId); //获取InternalProcess方法 MethodInfo methodInfo = this.GetType().GetMethod("InternalProcess", BindingFlags.NonPublic | BindingFlags.Instance); string executerMethodName = methodInfo.ReflectedType.FullName + "." + methodInfo.Name; string checkerMethodName = methodInfo.ReflectedType.FullName + "." + methodInfo.Name; //将方式实例和方式实例的参数都存到消息的属性中去。 //message.putUserProperties("executerMethodParameter", data); message.putUserProperties("executerMethod", executerMethodName); //message.putUserProperties("checkerMethodParameter", data); message.putUserProperties("checkerMethod", checkerMethodName); //方式实例字典中不存在的话,则试图新增到字典中去 if (!ONSHelper.ExecuterMethodDictionary.ContainsKey(executerMethodName)) { ONSHelper.ExecuterMethodDictionary.TryAdd(executerMethodName, methodInfo); } if (!ONSHelper.CheckerMethodDictionary.ContainsKey(checkerMethodName)) { ONSHelper.CheckerMethodDictionary.TryAdd(checkerMethodName, methodInfo); } //实例化LocalTransactionExecuter对象 ONSLocalTransactionExecuter executer = new ONSLocalTransactionExecuter(); //定义消息结果对象 SendResultONS sendResultONS = null; //尝试发送 sendResultONS = TryToSend(producer, message, executer, key, errorTimes); //判断结果,一般走不到这步,因为如果发送有问题会直接抛出异常的 if (sendResultONS == null) { throw new Exception("发送TRAN消息失败。key=" + key); } //更新发送状态 accomplishment = true; //更新消费次数 producedTimes = 1; } catch (Exception e) { failureReason = "发送TRAN消息,key=" + key + ",在TranProducerService中(非Executer或Checker中),捕获异常" + e.ToString(); LogData(key, body, "", "", failureReason, accomplishment, producedTimes, false); return(false); } return(true); }