/// <summary> /// 添加MQTransaction注入 /// </summary> /// <param name="services"></param> /// <param name="optionsAction"></param> /// <returns></returns> public static IServiceCollection AddMQTransaction(this IServiceCollection services, Action <MQTransOptions> optionsaction) { var options = new MQTransOptions(); //执行委托中方法 optionsaction(options); options.CheckNull(); //使委托中配置注入容器 foreach (var register in options.Registers) { register.AddServices(services); } //注入全局配置 services.AddSingleton(options); //注入job services.AddHostedService <PublishMsgHostService>(); services.AddHostedService <QueryStatusHostService>(); //注入消费端 foreach (var consumer in options.ConsumerOptions) { services.AddScoped(consumer.ConsumerType); } //注入触发消费类 services.AddScoped <ConsumeMessageWorker>(); //http注入 services.AddHttpClient(); services.AddTransient <MQtransProxy>(); return(services); }
public EFMQPublisher(MQTransOptions options , IServiceProvider serviceProvider , EFOptions mySqlEFOptions , IMQGenerateMsgBody mQGenerateMsgBody , IMQTransRepository repository , IMQOperate mQOperate) { this.options = options; this.serviceProvider = serviceProvider; this.mySqlEFOptions = mySqlEFOptions; this.mQGenerateMsgBody = mQGenerateMsgBody; this.repository = repository; this.mQOperate = mQOperate; }
public async Task DoAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { IMQTransRepository repository = null; MQTransOptions options = null; MQtransProxy mQtransProxy = null; try { using (var scope = Services.CreateScope()) { IMQTransRedis redis = null; RedisOptions redisOptions = null; var logid = Guid.NewGuid().ToString(); repository = scope.ServiceProvider.GetService <IMQTransRepository>(); options = scope.ServiceProvider.GetService <MQTransOptions>(); mQtransProxy = scope.ServiceProvider.GetService <MQtransProxy>(); redis = scope.ServiceProvider.GetService <IMQTransRedis>(); redisOptions = scope.ServiceProvider.GetService <RedisOptions>(); _logger.LogInformation($"{logid}->查询消息JOB*BEGIN*{options.ServiceName}*{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); var needSaveChange = false; if (redis.LockTake(ConstValues.LockQueryMsg + options.ServiceName, ConstValues.LockQueryMsg + options.ServiceName, TimeSpan.FromSeconds(redisOptions.LockMsgSenconds))) { try { var needQueryMsgs = repository.GetDealingMsgs(500, options.ServiceName, options.DefaultRetryCount); if (needQueryMsgs != null && needQueryMsgs.Count > 0) { foreach (var request in needQueryMsgs) { var resultstr = await mQtransProxy.Post(request.query_url, new[] { request.id }); if (!string.IsNullOrEmpty(resultstr)) { var result = JsonConvert.DeserializeObject <List <QueryStatusRequest> >(resultstr); if (result != null)//找到了 { var queryresult = result.Any(e => e.Id == request.id); repository.UpdateCallbackStatus(request, queryresult, options.DefaultRetryCount); needSaveChange = true; } } } } } catch (Exception ex) { _logger.LogError($"{logid}->查询消息JOB*{ex.ToString()}"); } finally { if (needSaveChange) { if (!repository.SaveChange()) { _logger.LogError($"{logid}->发送消息JOB*保存失败"); } } var a = redis.LockRelease(ConstValues.LockQueryMsg + options.ServiceName, ConstValues.LockQueryMsg + options.ServiceName); _logger.LogInformation($"{logid}->查询消息JOB*END*{options.ServiceName}*{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); } } } } catch (Exception ex) { _logger.LogError("查询消息JOB ERR:" + ex.ToString()); } //3min Thread.Sleep(1000 * 60 * options.JobFrequencyMinute); } }
public async Task DoAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { MQTransOptions options = null; IMQTransRepository repository = null; IMQOperate mqOperate = null; IMQGenerateMsgBody generateMsgBody = null; try { using (var scope = Services.CreateScope()) { IMQTransRedis redis = null; RedisOptions redisOptions = null; var logid = Guid.NewGuid().ToString(); _logger.LogInformation($"{logid}->发送消息JOB*BEGIN*{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); repository = scope.ServiceProvider.GetService <IMQTransRepository>(); mqOperate = scope.ServiceProvider.GetService <IMQOperate>(); generateMsgBody = scope.ServiceProvider.GetService <IMQGenerateMsgBody>(); options = scope.ServiceProvider.GetService <MQTransOptions>(); redis = scope.ServiceProvider.GetService <IMQTransRedis>(); redisOptions = scope.ServiceProvider.GetService <RedisOptions>(); var needSaveChange = false; if (redis.LockTake(ConstValues.LockSendMsg + options.ServiceName, options.ServiceName, TimeSpan.FromSeconds(redisOptions.LockMsgSenconds))) { var needPublishMsgs = repository.GetNeedPublishMsgs(100, options.ServiceName); _logger.LogInformation($"{logid}->发送消息JOB*COUNT*{needPublishMsgs.Count}*{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); try { foreach (var msg in needPublishMsgs) { var result = mqOperate.DirectPublish(generateMsgBody.GenerateQueueConfig(msg), JsonConvert.DeserializeObject <Message>(msg.message)); if (result.IsSucess) { needSaveChange = true; repository.UpdateSuccessStatus(msg, options.ExpiresMinute); } else { //发送失败,不做处理,会自动重新发起 _logger.LogError($"{logid}->发送消息JOB*未发送成功{JsonConvert.SerializeObject(result)}"); } } } catch (Exception ex) { //未查到,不做处理,会自动重新发起 _logger.LogError($"{logid}->发送消息JOB*{ex.ToString()}"); } finally { if (needSaveChange) { if (!repository.SaveChange()) { _logger.LogError($"{logid}->发送消息JOB*保存失败"); } } var a = redis.LockRelease(ConstValues.LockSendMsg + options.ServiceName, options.ServiceName); _logger.LogError($"{logid}->发送消息JOB*END*{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); } } } } catch (Exception ex) { _logger.LogError("发送消息JOB ERR:" + ex.ToString()); } //3min Thread.Sleep(1000 * 60 * options.JobFrequencyMinute); } }
/// <summary> /// 发消息时必填,防止分布式系统job重复执行。使用CSRedis操作redis。也可用其他,但需要开发 /// </summary> /// <param name="options"></param> /// <param name="redisOptions"></param> public static void UseCSRedisRedis(this MQTransOptions options, RedisOptions redisOptions) { options.Regist(new CSRedisRegister(redisOptions)); }
/// <summary> /// 发消息时必填,防止分布式系统job重复执行。使用StackExchangeRedis操作redis。也可用其他,但需要开发 /// </summary> /// <param name="options"></param> /// <param name="redisOptions"></param> public static void UseStackExchangeRedis(this MQTransOptions options, RedisOptions redisOptions) { options.Regist(new StackExchangeRedisRegister(redisOptions)); }
/// <summary> /// 使用RabbitMQ做消息。也可用Kafka,但需要开发 /// </summary> /// <param name="options"></param> /// <param name="mqoptions"></param> public static void UseRabbitMQ(this MQTransOptions options, RabbitMQOptions mqoptions) { options.Regist(new RabbitMQRegister(mqoptions)); }
/// <summary> /// 使用EF存储。也可用Dapper等框架,但需要开发 /// </summary> /// <typeparam name="TDbContext"></typeparam> /// <param name="options"></param> /// <param name="mysqption"></param> public static void UseEF <TDbContext>(this MQTransOptions options, EFOptions mysqption) { mysqption.MQDbContext = typeof(TDbContext); options.Regist(new EFRegister <TDbContext>(mysqption)); }
public ConsumeMessageWorker(IMQOperate mQOperate, MQTransOptions mQTransOptions) { this.mQOperate = mQOperate; this.mQTransOptions = mQTransOptions; }
public RabbitGenerateMsgBody(IMQOptions mqoptions, MQTransOptions options) { this.mqoptions = mqoptions as RabbitMQOptions; this.options = options; }