public bool TryConnect() { _logger.LogInformation("RabbitMQ is trying to connect...."); lock (sync_root) { var policy = RetryPolicy.Handle <SocketException>() .Or <BrokerUnreachableException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex, "RabbitMQ Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message); } ); policy.Execute(() => { _connection = _connectionFactory .CreateConnection(); }); if (IsConnected) { _connection.ConnectionShutdown += OnConnectionShutdown; _connection.CallbackException += OnCallbackException; _connection.ConnectionBlocked += OnConnectionBlocked; _logger.LogInformation("RabbitMQ acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connection.Endpoint.HostName); return(true); } else { _logger.LogCritical("FATAL ERROR: RabbitMQ connections could not be created and opened"); return(false); } } }
public bool TryConnect() { Console.WriteLine("RabbitMQ客户端正在尝试连接"); lock (sync_root) { var policy = RetryPolicy.Handle <SocketException>() .Or <BrokerUnreachableException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Console.WriteLine($"RabbitMQ客户端在{time}s ({ex.Message})"); } ); //在策略中执行指定的操作。 policy.Execute(() => { //创建到指定端点的连接 _connection = _connectionFactory .CreateConnection(); }); if (IsConnected) { _connection.ConnectionShutdown += OnConnectionShutdown; _connection.CallbackException += OnCallbackException; _connection.ConnectionBlocked += OnConnectionBlocked; Console.WriteLine($"RabbitMQ客户端获得了一个到'{_connection.Endpoint.HostName}'的持久连接,并订阅了失败事件"); return(true); } else { Console.WriteLine("致命错误:RabbitMQ连接无法创建和打开"); return(false); } } }
public bool TryConnect() { lock (sync_root) { if (!IsConnected) { _logger.LogInformation($"Nats client is trying to connect {_options.Url}"); var policy = RetryPolicy.Handle <NATSNoServersException>() .Or <NATSConnectionException>() .WaitAndRetry(5, retryAttemp => TimeSpan.FromSeconds(Math.Pow(2, retryAttemp)), (ex, time) => { _logger.LogWarning(ex, "NATS Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message); }); policy.Execute(() => { _connection = new ConnectionFactory().CreateConnection(_options.Url); }); } return(IsConnected); } }
public void Publish(IntegrationEvent @event) { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { }); var eventName = @event.GetType().Name; using (var channel = _persistentConnection.CreateModel()) { channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent channel.BasicPublish( exchange: BROKER_NAME, routingKey: eventName, mandatory: true, basicProperties: properties, body: body); }); } }
public bool TryConnect() { _logger.Info("RabbitMQ Client is trying to connect"); lock (sync_root) { var policy = RetryPolicy.Handle <SocketException>() .Or <BrokerUnreachableException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.Warn(ex.ToString()); } ); policy.Execute(() => { _connection = _connectionFactory .CreateConnection(); }); if (IsConnected) { _connection.ConnectionShutdown += OnConnectionShutdown; _connection.CallbackException += OnCallbackException; _connection.ConnectionBlocked += OnConnectionBlocked; _logger.Info($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events"); return(true); } _logger.Fatal("FATAL ERROR: RabbitMQ connections could not be created and opened"); return(false); } }
private RetryPolicy GetRetryPolicy(int retryCount, Action <Exception, TimeSpan> onRetry) { return(RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), onRetry)); }
public IServiceProvider ConfigureServices(IServiceCollection services) { string env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); string configsConnectionString; string usersConnectionString; string rabbitHostString; if (env == "Development") { usersConnectionString = "Server=localhost;Database=microstarter.identity_users;Username=doom;Password=machine"; configsConnectionString = "Server=localhost;Database=microstarter.identity_config;Username=doom;Password=machine"; rabbitHostString = "rabbitmq://localhost"; } else // if (env == "Docker_Production") { usersConnectionString = "Server=postgre_name;Database=microstarter.identity_users;Username=doom;Password=machine"; configsConnectionString = "Server=postgre_name;Database=microstarter.identity_config;Username=doom;Password=machine"; rabbitHostString = "rabbitmq://MicroStarterEventBus"; } var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; services.AddDbContext <UserDbContext>(options => options.UseNpgsql(usersConnectionString, sql => sql.MigrationsAssembly(migrationsAssembly)) ); services.AddIdentity <ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores <UserDbContext>(); services.AddTransient <IEmailSender, AuthMessageSender>(); services.AddTransient <ISmsSender, AuthMessageSender>(); services.AddIdentityServer(options => { options.Events.RaiseSuccessEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; }) .AddDeveloperSigningCredential() // .AddTestUsers(TestUsers.Users) .AddAspNetIdentity <ApplicationUser>() // You can Configure Profile Service for your needs .AddProfileService <AuthProfileService>() // this adds the config data from DB (clients, resources, CORS) .AddConfigurationStore(options => { options.ResolveDbContextOptions = (provider, builder) => { builder.UseNpgsql(configsConnectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }; }) // this adds the operational data from DB (codes, tokens, consents) .AddOperationalStore(options => { options.ConfigureDbContext = (builder) => { builder.UseNpgsql(configsConnectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }; // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; // options.TokenCleanupInterval = 10; // interval in seconds, short for testing }) .AddConfigurationStoreCache(); services.AddMassTransit(p => { // p.AddConsumer<SomeEventHappenedConsumer>(); }); var _retryCount = 8; var policy = RetryPolicy.Handle <SocketException>() .Or <BrokerUnreachableException>() .Or <RabbitMqConnectionException>() .OrInner <BrokerUnreachableException>() .OrInner <RabbitMqConnectionException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Console.WriteLine("Could not connect Broker Trying Again"); Console.WriteLine(ex); Console.WriteLine("Retrying RabbitMq Connection"); } ); IServiceProvider prov = services.BuildServiceProvider(); IBusControl busControl; policy.Execute(() => { busControl = Bus.Factory.CreateUsingRabbitMq(cfg => { var host = cfg.Host(new Uri(rabbitHostString), "/", h => { h.Username("doom"); h.Password("machine"); }); cfg.ReceiveEndpoint(host, e => { e.PrefetchCount = 8; // Add Your Event Consumers Here // If you want Inject services to consumer, pass provider param // e.Consumer<SomeEventHappenedConsumer>(provider) }); }); services.AddSingleton(provider => busControl); }); services.AddSingleton <IPublishEndpoint>(provider => provider.GetRequiredService <IBusControl>()); services.AddSingleton <ISendEndpointProvider>(provider => provider.GetRequiredService <IBusControl>()); services.AddSingleton <IBus>(provider => provider.GetRequiredService <IBusControl>()); // Register with IHostedService To Start bus in Application Start services.AddSingleton <Microsoft.Extensions.Hosting.IHostedService, BusService>(); services.AddSingleton <LocService>(); services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddScoped <ClientIdFilter>(); services.AddScoped <ClientSelector>(); services.Configure <RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new ClientViewLocationExpander()); }); services.Configure <RequestLocalizationOptions>( options => { var supportedCultures = new List <CultureInfo> { new CultureInfo("en-US"), new CultureInfo("de-CH"), new CultureInfo("fr-CH") }; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; var providerQuery = new LocalizationQueryProvider { QureyParamterName = "ui_locales" }; // Cookie is required for the logout, query parameters at not supported with the endsession endpoint // Only works in the same domain var providerCookie = new LocalizationCookieProvider { CookieName = "defaultLocale" }; // options.RequestCultureProviders.Insert(0, providerCookie); options.RequestCultureProviders.Insert(0, providerQuery); }); services.AddMvc() .AddViewLocalization() .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => { var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName); return(factory.Create("SharedResource", assemblyName.Name)); }; }); return(services.BuildServiceProvider(validateScopes: false)); }
private bool TryConnect() { if (IsConnected) { return(true); } lock (syncRoot) { if (IsConnected) { return(true); } //_logger.LogInformation("RabbitMQ Client is trying to connect"); if (connection != null) { connection.ConnectionShutdown -= OnConnectionShutdown; connection.CallbackException -= OnCallbackException; connection.ConnectionBlocked -= OnConnectionBlocked; connection.Dispose(); } var policy = RetryPolicy.Handle <SocketException>() .Or <BrokerUnreachableException>() .WaitAndRetry(retryCount: 3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { //_logger.LogWarning(ex, "RabbitMQ Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message); } ); policy.Execute(() => { connection = connectionFactory.CreateConnection(); }); if (IsConnected) { connection !.ConnectionShutdown += OnConnectionShutdown; connection !.CallbackException += OnCallbackException; connection !.ConnectionBlocked += OnConnectionBlocked; //_logger.LogInformation("RabbitMQ Client acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connection.Endpoint.HostName); return(true); } else { //_logger.LogCritical("FATAL ERROR: RabbitMQ connections could not be created and opened"); return(false); } } void OnConnectionBlocked(object?sender, ConnectionBlockedEventArgs e) { //_logger.LogWarning("A RabbitMQ connection is shutdown. Trying to re-connect..."); TryConnect(); } void OnCallbackException(object?sender, CallbackExceptionEventArgs e) { //_logger.LogWarning("A RabbitMQ connection throw exception. Trying to re-connect..."); TryConnect(); } void OnConnectionShutdown(object?sender, ShutdownEventArgs reason) { //_logger.LogWarning("A RabbitMQ connection is on shutdown. Trying to re-connect..."); TryConnect(); } }
public string PublishRpc(IntegrationEvent @event) { string result = string.Empty; if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex.ToString()); }); using (var channel = _persistentConnection.CreateModel()) { BlockingCollection <string> respQueue = new BlockingCollection <string>(); var eventName = @event.GetType() .Name; channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); var replyQueueName = channel.QueueDeclare().QueueName; var consumer = new EventingBasicConsumer(channel); var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); var correlationId = Guid.NewGuid().ToString(); consumer.Received += (model, ea) => { var receiveMsg = ea.Body; var response = Encoding.UTF8.GetString(receiveMsg); if (ea.BasicProperties.CorrelationId == correlationId) { respQueue.Add(response); } }; policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent properties.CorrelationId = correlationId; properties.ReplyTo = replyQueueName; channel.BasicPublish(exchange: BROKER_NAME, routingKey: eventName, mandatory: true, basicProperties: properties, body: body); channel.BasicConsume( consumer: consumer, queue: replyQueueName, autoAck: true); }); result = respQueue.Take(); } return(result); }
public void Publish(IntegrationEvent @event, byte priority = 0) { logger.Info("Se inicia la ejecución del método Publish"); logger.Debug("Argumentos del método Publish: event - {}, priority - {}", @event, priority); if (!_persistentConnection.IsConnected) { logger.Trace("No se ha establecido la conexión al Message Broker"); _persistentConnection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { logger.Warn("No se ha podido establecer la conexión al Message Broker"); logger.Debug("Argumentos del action onRetry: Exception - {}, TimeSpan - {}", ex, time); }); logger.Trace("Se procede a crear el Channel"); using (var channel = _persistentConnection.CreateModel()) { logger.Debug("Valor de la variable channel - {}", channel); logger.Trace("Se obtiene el nombre del evento y se almacena en la variable eventName"); var eventName = @event.GetType() .Name; logger.Debug("Valor de la variable eventName - {}", eventName); logger.Trace("Se declara el Exchange en el Message Broker"); logger.Debug("Argumentos de channel.ExchangeDeclare: exchange - {}, type - {}, durable - {}", BROKER_NAME, "direct", true); channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct", durable: true); logger.Trace("Se obtiene la instancia del IntegrationEvent"); var message = JsonConvert.SerializeObject(@event); logger.Debug("Valor de la variable message - {}", message); logger.Trace("Se obtiene el payload del IntegrationEvent"); var body = Encoding.UTF8.GetBytes(message); logger.Debug("Valor de la variable body - {}", body); logger.Trace("Se define la política para la publicación del evento"); policy.Execute(() => { logger.Trace("Se inicia la creación de las propiedades del mensaje"); var properties = channel.CreateBasicProperties(); logger.Debug("Valor de la variable properties - {}", properties); logger.Trace("Se establece el DeliveryMode"); properties.DeliveryMode = 2; // persistent logger.Debug("Valor del properties.DeliveryMode - {}", properties.DeliveryMode); logger.Trace("Se establece el Priority"); properties.Priority = priority; logger.Debug("Valor del properties.Priority - {}", properties.Priority); logger.Trace("Se realiza la publicación del mensaje en el Message Broker"); logger.Debug("Argumentos de channel.BasicPublish: exchange - {}, routingKey - {}, mandatory - {}, basicProperties - {}, body - {}", BROKER_NAME, eventName, true, properties, body); channel.BasicPublish(exchange: BROKER_NAME, routingKey: eventName, mandatory: true, basicProperties: properties, body: body); }); } }
/// <summary> /// Get retry policy /// </summary> /// <returns></returns> protected PolicyBuilder GetPolicyBuilder() { return(RetryPolicy.Handle <MongoConnectionException>( i => i.InnerException.GetType() == typeof(IOException) || i.InnerException.GetType() == typeof(SocketException))); }
/// <summary> /// 发送消息 /// </summary> public void Publish( Dictionary <string, Dictionary <string, string> > Events, Action <List <string> > ackHandler = null, Action <List <string> > nackHandler = null, Action <List <string> > returnHandler = null, int EventDelaySeconds = 0, int TimeoutMilliseconds = 500) { try { if (!IsConnected) { TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <System.IO.IOException>() .Or <RabbitMQ.Client.Exceptions.AlreadyClosedException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { XuHos.Common.LogHelper.WriteWarn($"publish events wait and Retry", ex); }); using (var _channel = CreateModel()) { var DeliveryTags = new Dictionary <ulong, string>(); var ReturnTags = new Dictionary <string, string>(); //消息无法投递失被退回(如:队列找不到) _channel.BasicReturn += (object sender, BasicReturnEventArgs e) => { var EventIDs = new List <string>(); if (!string.IsNullOrEmpty(e.BasicProperties.MessageId)) { EventIDs.Add(e.BasicProperties.MessageId); ReturnTags.Add(e.BasicProperties.MessageId, e.RoutingKey); } if (returnHandler != null && EventIDs.Count > 0) { returnHandler(EventIDs); } }; //消息路由到队列并持久化后执行 _channel.BasicAcks += (object sender, BasicAckEventArgs e) => { var EventIDs = new List <string>(); if (e.Multiple) { foreach (var EventID in DeliveryTags.Where(a => a.Key < e.DeliveryTag + 1).Select(a => a.Value)) { if (!EventIDs.Contains(EventID) && !ReturnTags.ContainsKey(EventID)) { EventIDs.Add(EventID); } } } else { var EventID = DeliveryTags[e.DeliveryTag]; if (!EventIDs.Contains(EventID) && !ReturnTags.ContainsKey(EventID)) { EventIDs.Add(DeliveryTags[e.DeliveryTag]); } } if (ackHandler != null && EventIDs.Count > 0) { ackHandler(EventIDs); } }; //消息投递失败 _channel.BasicNacks += (object sender, BasicNackEventArgs e) => { var EventIDs = new List <string>(); //批量确认 if (e.Multiple) { foreach (var EventID in DeliveryTags.Where(a => a.Key < e.DeliveryTag + 1).Select(a => a.Value)) { if (!EventIDs.Contains(EventID)) { EventIDs.Add(EventID); } } } else { var EventID = DeliveryTags[e.DeliveryTag]; if (!EventIDs.Contains(EventID)) { EventIDs.Add(EventID); } } if (nackHandler != null && EventIDs.Count > 0) { nackHandler(EventIDs); } }; policy.Execute(() => { _channel.ConfirmSelect(); }); foreach (var msg in Events) { policy.Execute(() => { var EventId = msg.Key; var json = msg.Value["Body"]; var routeKey = msg.Value["EventTypeName"]; byte[] bytes = Encoding.UTF8.GetBytes(json); //设置消息持久化 IBasicProperties properties = _channel.CreateBasicProperties(); properties.DeliveryMode = 2; properties.MessageId = msg.Key; if (!DeliveryTags.ContainsValue(EventId)) { DeliveryTags.Add((ulong)DeliveryTags.Count + 1, EventId); } //需要发送延时消息 if (EventDelaySeconds > 0) { Dictionary <string, object> dic = new Dictionary <string, object>(); dic.Add("x-expires", EventDelaySeconds * 10000); //队列过期时间 dic.Add("x-message-ttl", EventDelaySeconds * 1000); //当一个消息被推送在该队列的时候 可以存在的时间 单位为ms,应小于队列过期时间 dic.Add("x-dead-letter-exchange", _exchange); //过期消息转向路由 dic.Add("x-dead-letter-routing-key", routeKey); //过期消息转向路由相匹配routingkey routeKey = routeKey + "_DELAY_" + EventDelaySeconds; //创建一个队列 _channel.QueueDeclare( queue: routeKey, durable: true, exclusive: false, autoDelete: false, arguments: dic); _channel.BasicPublish( exchange: "", mandatory: true, routingKey: routeKey, basicProperties: properties, body: bytes); } else { _channel.BasicPublish( exchange: _exchange, mandatory: true, routingKey: routeKey, basicProperties: properties, body: bytes); } }); } policy.Execute(() => { _channel.WaitForConfirmsOrDie(TimeSpan.FromSeconds(TimeoutMilliseconds)); }); } } catch (Exception ex) { XuHos.Common.LogHelper.WriteError(ex); } }
protected virtual TResult Retry <TResult>(Func <TResult> action) => RetryPolicy .Handle <MongoConnectionException>(i => i.InnerException.GetType() == typeof(IOException) || i.InnerException.GetType() == typeof(SocketException)) .Retry(3) .Execute(action);
/// <summary> /// 使用消息总线订阅者 /// 作者:郭明 /// 日期:2017年11月21日 /// </summary> /// <param name="app"></param> public static IServiceProvider UseSubscriber(this IServiceProvider serviceProvider, Action <IEventBus> setupSubscriberHandler) { var eventBus = serviceProvider.GetRequiredService <IEventBus>(); var logger = serviceProvider.GetRequiredService <ILogger <IEventLogger> >(); var eventLogService = serviceProvider.GetRequiredService <IEventLogger>(); //设置重试策略 var policy = RetryPolicy.Handle <Exception>() .Retry(3, (ex, time) => { logger.LogError(ex, ex.ToString()); }); //订阅消息 eventBus.Subscribe((eventId, queueName) => { //消息消费成功执行以下代码 if (!string.IsNullOrEmpty(eventId)) { //出现异常则重试3次 policy.Execute(async() => { //这里可能会重复执行要保持幂等 await eventLogService.MarkEventConsumeAsRecivedAsync(eventId, queueName); }); } }, async(eventId, queueName, outEx, eventObj) => { //消息消费失败执行以下代码 if (outEx != null) { logger.LogError(outEx, outEx.Message); } if (!string.IsNullOrEmpty(eventId)) { //使用重试策略执行,出现错误立即重试3次 return(await policy.Execute(async() => { //这里可能会重复,需要保持幂等 var times = await eventLogService.MarkEventConsumeAsFailedAsync(eventId, queueName); //记录重试次数(在阀值内则重新写队列) if (times > 3) { return false; } else { return true; } })); } return(true); }); setupSubscriberHandler(eventBus); return(serviceProvider); }
private IModel CreateConsumerChannel() { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } var channel = _persistentConnection.CreateModel(); channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); channel.ExchangeDeclare(exchange: $"dlx_{BROKER_NAME}", type: "direct"); IDictionary <string, object> args = new Dictionary <string, object>(); args.Add(new KeyValuePair <string, object>("x-dead-letter-exchange", $"dlx_{BROKER_NAME}")); channel.QueueDeclare(queue: _queueName, durable: true, exclusive: false, autoDelete: false, arguments: args); channel.QueueDeclare(queue: $"dlx_{_queueName}", durable: true, exclusive: false, autoDelete: false, arguments: null); var consumer = new EventingBasicConsumer(channel); consumer.Received += async(model, ea) => { try { var eventName = ea.RoutingKey; var message = Encoding.UTF8.GetString(ea.Body); var policy = RetryPolicy.Handle <Exception>() .WaitAndRetryAsync(_pTimeSpans, (ex, time, context) => { _logger.Error("Subscribe/RetryPolicy", "EventBusRabbitMQ", $"message:{ea.Body}--count:{context.Count}--time:{time}", ex); }); await policy.ExecuteAsync(async() => { await ProcessEvent(eventName, message); }); channel.BasicAck(ea.DeliveryTag, multiple: false); } catch (Exception ex) { _logger.Error("Subscribe/RetryPolicy", "EventBusRabbitMQ", $"message:{ea.Body}", ex); channel.BasicReject(ea.DeliveryTag, false); } }; channel.BasicConsume(queue: _queueName, noAck: false, consumer: consumer); channel.CallbackException += (sender, ea) => { _consumerChannel.Dispose(); _consumerChannel = CreateConsumerChannel(); }; return(channel); }
/// <summary> /// 发送消息 /// </summary> async Task Enqueue( Dictionary <string, Dictionary <string, string> > Events, Action <List <string> > ackHandler = null, Action <List <string> > nackHandler = null, Action <List <string> > returnHandler = null, int EventDelaySeconds = 0, int TimeoutMilliseconds = 500, int BatchSize = 500) { try { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <System.IO.IOException>() .Or <AlreadyClosedException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex.ToString()); }); //消息发送成功后回调后需要修改数据库状态,改成本地做组缓存后,再批量入库。(性能提升百倍) var _batchBlock_BasicReturn = new BatchBlock <string>(BatchSize); var _batchBlock_BasicAcks = new BatchBlock <string>(BatchSize); var _batchBlock_BasicNacks = new BatchBlock <string>(BatchSize); var _actionBlock_BasicReturn = new ActionBlock <string[]>(EventIDs => { if (returnHandler != null && EventIDs.Length > 0) { returnHandler(EventIDs.ToList()); } }); var _actionBlock_BasicAcks = new ActionBlock <string[]>(EventIDs => { if (ackHandler != null && EventIDs.Length > 0) { ackHandler(EventIDs.ToList()); } }); var _actionBlock_BasicNacks = new ActionBlock <string[]>(EventIDs => { if (nackHandler != null && EventIDs.Length > 0) { nackHandler(EventIDs.ToList()); } }); _batchBlock_BasicReturn.LinkTo(_actionBlock_BasicReturn); _batchBlock_BasicAcks.LinkTo(_actionBlock_BasicAcks); _batchBlock_BasicNacks.LinkTo(_actionBlock_BasicNacks); _batchBlock_BasicReturn.Completion.ContinueWith(delegate { _actionBlock_BasicReturn.Complete(); }); _batchBlock_BasicAcks.Completion.ContinueWith(delegate { _actionBlock_BasicAcks.Complete(); }); _batchBlock_BasicNacks.Completion.ContinueWith(delegate { _actionBlock_BasicNacks.Complete(); }); using (var _channel = _persistentConnection.CreateModel()) { //保存EventId和DeliveryTag 映射 var deliveryTags = new Dictionary <ulong, string>(); var returnEventIds = new System.Collections.Hashtable(); //消息无法投递失被退回(如:队列找不到) _channel.BasicReturn += (object sender, BasicReturnEventArgs e) => { if (!string.IsNullOrEmpty(e.BasicProperties.MessageId)) { _batchBlock_BasicReturn.Post(e.BasicProperties.MessageId); returnEventIds.Add(e.BasicProperties.MessageId, false); } }; //消息路由到队列并持久化后执行 _channel.BasicAcks += (object sender, BasicAckEventArgs e) => { var EventIDs = new List <string>(); if (e.Multiple) { foreach (var EventID in deliveryTags.Where(a => a.Key < e.DeliveryTag + 1).Select(a => a.Value)) { if (!EventIDs.Contains(EventID) && !returnEventIds.ContainsKey(EventID)) { EventIDs.Add(EventID); } } } else { var EventID = deliveryTags[e.DeliveryTag]; if (!EventIDs.Contains(EventID) && !returnEventIds.ContainsKey(EventID)) { EventIDs.Add(deliveryTags[e.DeliveryTag]); } } EventIDs.ForEach(eventId => { _batchBlock_BasicAcks.Post(eventId); }); }; //消息投递失败 _channel.BasicNacks += (object sender, BasicNackEventArgs e) => { var EventIDs = new List <string>(); //批量确认 if (e.Multiple) { foreach (var EventID in deliveryTags.Where(a => a.Key < e.DeliveryTag + 1).Select(a => a.Value)) { if (!EventIDs.Contains(EventID)) { EventIDs.Add(EventID); } } } else { var EventID = deliveryTags[e.DeliveryTag]; if (!EventIDs.Contains(EventID)) { EventIDs.Add(EventID); } } EventIDs.ForEach(eventId => { _batchBlock_BasicNacks.Post(eventId); }); }; policy.Execute(() => { _channel.ConfirmSelect(); }); foreach (var msg in Events) { policy.Execute(() => { var EventId = msg.Key; var json = msg.Value["Body"]; var routeKey = msg.Value["EventTypeName"]; byte[] bytes = Encoding.UTF8.GetBytes(json); //设置消息持久化 IBasicProperties properties = _channel.CreateBasicProperties(); properties.DeliveryMode = 2; properties.MessageId = msg.Key; if (!deliveryTags.ContainsValue(EventId)) { deliveryTags.Add((ulong)deliveryTags.Count + 1, EventId); } //需要发送延时消息 if (EventDelaySeconds > 0) { Dictionary <string, object> dic = new Dictionary <string, object>(); dic.Add("x-expires", EventDelaySeconds * 10000); //队列过期时间 dic.Add("x-message-ttl", EventDelaySeconds * 1000); //当一个消息被推送在该队列的时候 可以存在的时间 单位为ms,应小于队列过期时间 dic.Add("x-dead-letter-exchange", _exchange); //过期消息转向路由 dic.Add("x-dead-letter-routing-key", routeKey); //过期消息转向路由相匹配routingkey routeKey = routeKey + "_DELAY_" + EventDelaySeconds; //创建一个队列 _channel.QueueDeclare( queue: routeKey, durable: true, exclusive: false, autoDelete: false, arguments: dic); _channel.BasicPublish( exchange: "", mandatory: true, routingKey: routeKey, basicProperties: properties, body: bytes); } else { _channel.BasicPublish( exchange: _exchange, mandatory: true, routingKey: routeKey, basicProperties: properties, body: bytes); } }); } policy.Execute(() => { _channel.WaitForConfirms(TimeSpan.FromSeconds(TimeoutMilliseconds)); }); } _batchBlock_BasicAcks.Complete(); _batchBlock_BasicNacks.Complete(); _batchBlock_BasicReturn.Complete(); _actionBlock_BasicNacks.Completion.Wait(); _actionBlock_BasicAcks.Completion.Wait(); _actionBlock_BasicReturn.Completion.Wait(); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
public async Task <bool> Correo(ComplementEmail _complementEmail) { bool resp = false; try { var policy = RetryPolicy.Handle <Exception>() .Or <BrokerUnreachableException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(1, retryAttempt)), (ex, time) => { contador++; if (_retryCount.Equals(contador)) { Console.WriteLine($"Intentos de Conexion a Rabit{_retryCount}"); contador = 0; } else { Console.WriteLine($"intentos {contador}"); } }); policy.Execute(() => { _log.Info("Iniciando Proceso de envio correo a RabbitMQ"); var parametro = new ConnectionFactory { HostName = parametersMessage.Host, Port = AmqpTcpEndpoint.UseDefaultPort, UserName = parametersMessage.UserRabbitMQ, Password = parametersMessage.Password }; using (var connection = parametro.CreateConnection()) { _log.Info("Conexion Exitosa a RabbitMQ !"); using (var canales = connection.CreateModel()) { var _emailRequest = new List <EmailRequest>() { new EmailRequest() { CuentaMail = cuentaEmail.CuentaId, De = cuentaEmail.EnviaMail, Para = _complementEmail.Para, CC = _complementEmail.CopiaMail, Asunto = _complementEmail.Asunto, ParametrosDinamicos = parametros, Base64Files = base64 } }; var properties = canales.CreateBasicProperties(); properties.DeliveryMode = 2; canales.ConfirmSelect(); canales.BasicPublish( exchange: parametersMessage.Channel, routingKey: parametersMessage.Key, basicProperties: properties, body: Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(_emailRequest))); canales.WaitForConfirmsOrDie(); _emailRequest.Clear(); canales.Close(); } } }); resp = true; } catch (Exception ex) { } Dispose(); return(await Task.FromResult(resp)); }
private async Task <bool> PublishForWaitAsync(string exchange, string queue, string routeKey, IEvent @event, int retryCount = 0) { if (!_connection.IsConnected) { _connection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogInformation($"Could not publish event: {@event.EventId} after {time.TotalSeconds:n1}s ({ex.Message})"); }); var message = @event.ToJsonString(); var body = Encoding.UTF8.GetBytes(message); if (!_channelDict.TryGetValue($"{exchange}:{queue}", out var channel)) { channel = _connection.CreateModel(); channel.ExchangeDeclare(exchange: exchange, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: null); channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null); } var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent properties.Headers["retry-count"] = retryCount; channel.ConfirmSelect(); // 开启发布确认 using (var scope = _serviceScopeFactory.CreateScope()) { try { var context = new RabbitMQEventPublishContext { ServiceProvider = scope.ServiceProvider, EventBus = this, RouteKey = routeKey, RetryCount = retryCount, Exchange = exchange, Queue = queue, BasicProperties = properties, }; if (OnProducing != null) { await OnProducing(@event, context); } policy.Execute(() => { channel.BasicPublish( exchange: exchange, routingKey: routeKey, mandatory: true, basicProperties: properties, body: body); }); if (OnProduced != null) { await OnProduced(@event, context); } return(channel.WaitForConfirms()); } catch (Exception ex) { if (OnProductError == null) { throw; } var errorContext = new RabbitMQEventPublishErrorContext { ServiceProvider = scope.ServiceProvider, EventBus = this, RouteKey = routeKey, RetryCount = retryCount, Exception = ex, Exchange = exchange, Queue = queue, BasicProperties = properties }; await OnProductError(@event, errorContext); return(false); } } }
public void Publish <TIntegrationEvent>(TIntegrationEvent eventData) where TIntegrationEvent : IntegrationEvent { var eventType = eventData.GetType(); var _queueName = _options.QueueName; var _exchange = _options.ExchangeName; var _exchangeType = _options.ExchangeType; var _routingKey = eventType.Name; var _retryCount = _options.RetryCount; //Settings Queue var _druable = _options.Druable; var _exclusive = _options.Exclusive; var _autodelete = _options.AutoDelete; var _args = _options.Args; var _settings = eventType.GetCustomAttributes(false).FirstOrDefault(x => x is RabbitMQSettingsAttribute) as RabbitMQSettingsAttribute; // Reset Config if has Attribute if (_settings != null) { if (!string.IsNullOrEmpty(_settings.ExchangeName)) { _exchange = _settings.ExchangeName; } if (!string.IsNullOrEmpty(_settings.ExchangeType)) { _exchangeType = _settings.ExchangeType; } if (!string.IsNullOrEmpty(_settings.QueueName)) { _queueName = _settings.QueueName; } if (!string.IsNullOrEmpty(_settings.RootingKey)) { _routingKey = _settings.RootingKey; } _druable = _settings.Druable; _exclusive = _settings.Exclusive; _autodelete = _settings.AutoDelete; _args = _settings.Args; } using (var channel = _connection.CreateModel()) { channel.ExchangeDeclare(exchange: _exchange, type: _exchangeType); channel.QueueDeclare(_queueName, _druable, _exclusive, _autodelete, _args); channel.QueueBind(queue: _queueName, exchange: _exchange, routingKey: _routingKey); eventData.JwtToken = _token; var message = JsonConvert.SerializeObject(eventData); var body = Encoding.UTF8.GetBytes(message); var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogError(ex, "Publish"); }); policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = eventData.DeliveryMode; //1 none-persistent, 2 persistent properties.ContentEncoding = "UTF8"; properties.ContentType = "application/json"; channel.BasicPublish(exchange: _exchange, routingKey: _routingKey, mandatory: _settings.Mandatory, basicProperties: properties, body: body); }); } }
public Task <bool> NewContent <T>(List <T> datos, string hoja) { bool _resp = false; try { var policyExcel = RetryPolicy.Handle <Exception>().Or <NullReferenceException>(). WaitAndRetry(4, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _log.Warn($"Intent Para crear el excel {time.Seconds}, {_fecha.FechaNow().Result}"); }); policyExcel.Execute(() => { if (datos.Count > 0) { var cantidad = extra.GetHeader(datos.FirstOrDefault()); headerRow = extra.Data(); dataconte = null; foreach (object obj in datos) { dataconte = new string[cantidad]; var indice = 0; properties = obj.GetType().GetProperties(); foreach (PropertyInfo property in properties) { attributes = property.GetCustomAttributes(typeof(DescripcionExcel), true); if (attributes.Length > 0) { myAttribute = (DescripcionExcel)attributes[0]; if (!myAttribute.Ignore) { if (property.GetValue(obj) != null) { dataconte[indice] = property.GetValue(obj).ToString(); } else { dataconte[indice] = ""; } } else { indice--; } } indice++; } data.Add(dataconte); } bool resp = Header(hoja).Result; if (resp) { resp = Content().Result; } _log.Info($"Archivo excel creado con exito {_fecha.FechaNow().Result}"); } }); } catch (Exception ex) { _log.Error($"Excel {ex.StackTrace}"); } Limpiar(); Dispose(true); return(Task.FromResult(_resp)); }
public void Publish(Event @event) { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogError(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); }); var eventName = @event.GetType().Name; _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); using (var channel = _persistentConnection.CreateModel()) { _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); channel.ExchangeDeclare( exchange: BROKER_ALT_NAME, type: ExchangeType.Direct, durable: true, autoDelete: false); channel.QueueDeclare( queue: RETRY_ALT_QUEUE, durable: true, exclusive: false, autoDelete: false); var exchangeArgs = new Dictionary <string, object> { { "alternate-exchange", BROKER_ALT_NAME } }; channel.ExchangeDeclare( exchange: BROKER_NAME, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: exchangeArgs); var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent properties.CorrelationId = Guid.NewGuid().ToString(); _logger.LogTrace($"Publishing event to RabbitMQ: {@event.Id}"); channel.BasicPublish( exchange: BROKER_NAME, routingKey: eventName, mandatory: true, basicProperties: properties, body: body); }); } }
/// <summary> /// 添加微服务依赖 /// </summary> /// <param name="services"></param> /// <returns></returns> public static IHummingbirdHostBuilder AddServiceRegistry(this IHummingbirdHostBuilder hostBuilder, Action <ServiceConfig> setupServiceConfig) { AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; _serviceConfig = _serviceConfig ?? new ServiceConfig(); if (setupServiceConfig != null) { setupServiceConfig(_serviceConfig); } var policy = RetryPolicy.Handle <Exception>() .Or <System.IO.IOException>() .WaitAndRetryForever(a => { return(TimeSpan.FromSeconds(5)); }, (ex, time) => { Console.WriteLine("WaitAndRetryForever" + ex.Message); }); policy.Execute(() => { var self_Register = _serviceConfig.SERVICE_SELF_REGISTER; _serviceConfig.SERVICE_REGISTRY_ADDRESS = _serviceConfig.SERVICE_REGISTRY_ADDRESS.Trim(); if (self_Register == null || self_Register.ToLower() == bool.TrueString.ToString().ToLower()) { var client = new ConsulClient(obj => { obj.Address = new Uri($"http://{_serviceConfig.SERVICE_REGISTRY_ADDRESS}:{_serviceConfig.SERVICE_REGISTRY_PORT}"); obj.Datacenter = _serviceConfig.SERVICE_REGION; obj.Token = _serviceConfig.SERVICE_REGISTRY_TOKEN; }); //计算健康检查地址 var SERVICE_80_CHECK_HTTP = _serviceConfig.SERVICE_80_CHECK_HTTP; if (!SERVICE_80_CHECK_HTTP.Contains("http://")) { SERVICE_80_CHECK_HTTP = $"http://{_serviceConfig.SERVICE_ADDRESS}:{_serviceConfig.SERVICE_PORT}/{SERVICE_80_CHECK_HTTP.TrimStart('/')}"; } var result = client.Agent.ServiceRegister(new AgentServiceRegistration() { ID = _serviceConfig.SERVICE_ID, Name = _serviceConfig.SERVICE_NAME, Address = _serviceConfig.SERVICE_ADDRESS, Port = int.Parse(_serviceConfig.SERVICE_PORT), Tags = new[] { _serviceConfig.SERVICE_TAGS }, EnableTagOverride = true, Check = new AgentServiceCheck() { Status = HealthStatus.Passing, HTTP = SERVICE_80_CHECK_HTTP, Interval = TimeSpan.FromSeconds(int.Parse(_serviceConfig.SERVICE_80_CHECK_INTERVAL.TrimEnd('s'))), //5秒执行一次健康检查 Timeout = TimeSpan.FromSeconds(int.Parse(_serviceConfig.SERVICE_80_CHECK_TIMEOUT.TrimEnd('s'))), //超时时间3秒 //TTL = TimeSpan.FromSeconds(int.Parse(_serviceConfig.SERVICE_80_CHECK_INTERVAL.TrimEnd('s')) * 3),//生存周期3个心跳包 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(int.Parse(_serviceConfig.SERVICE_80_CHECK_INTERVAL.TrimEnd('s')) * 3), //2个心跳包结束 } }).Result; Console.WriteLine($"ServiceRegister({_serviceConfig.SERVICE_ID}"); } }); return(hostBuilder); }
public bool Publish <IData>( IData msg, int EventDelaySeconds = 0, int TimeoutMillseconds = 500) where IData : XuHos.EventBus.IEvent { var policy = RetryPolicy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <System.IO.IOException>() .Or <RabbitMQ.Client.Exceptions.AlreadyClosedException>() .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { XuHos.Common.LogHelper.WriteWarn($"publish events wait and Retry", ex); }); if (!IsConnected) { TryConnect(); } try { _channel = GetModel(); return(policy.Execute(() => { string json = JsonConvert.SerializeObject(msg); byte[] bytes = Encoding.UTF8.GetBytes(json); var routeKey = msg.GetType().FullName; //设置消息持久化 IBasicProperties properties = _channel.CreateBasicProperties(); properties.DeliveryMode = 2; //是否需要确认,事务模式和Confirm不能同事开启 if (!_transactionUnCommit) { _channel.ConfirmSelect(); } //需要发送延时消息 if (EventDelaySeconds > 0) { Dictionary <string, object> dic = new Dictionary <string, object>(); dic.Add("x-expires", EventDelaySeconds * 10000); //队列过期时间 dic.Add("x-message-ttl", EventDelaySeconds * 1000); //当一个消息被推送在该队列的时候 可以存在的时间 单位为ms,应小于队列过期时间 dic.Add("x-dead-letter-exchange", _exchange); //过期消息转向路由 dic.Add("x-dead-letter-routing-key", routeKey); //过期消息转向路由相匹配routingkey routeKey = routeKey + "_DELAY_" + EventDelaySeconds; //创建一个队列 _channel.QueueDeclare( queue: routeKey, durable: true, exclusive: false, autoDelete: false, arguments: dic); _channel.BasicPublish( exchange: "", mandatory: true, routingKey: routeKey, basicProperties: properties, body: bytes); } else { _channel.BasicPublish(_exchange, routeKey, true, properties, bytes); } if (!_transactionUnCommit) { _channel.WaitForConfirmsOrDie(TimeSpan.FromMilliseconds(TimeoutMillseconds)); return true; } else { return true; } })); } catch (Exception ex) { XuHos.Common.LogHelper.WriteError(ex); return(false); } }