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);
                }
            }
        }
Пример #2
0
        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);
                }
            }
        }
Пример #3
0
        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);
                });
            }
        }
Пример #5
0
        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));
 }
Пример #7
0
        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));
        }
Пример #8
0
        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);
        }
Пример #10
0
        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);
                });
            }
        }
Пример #11
0
 /// <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)));
 }
Пример #12
0
        /// <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);
            }
        }
Пример #13
0
 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);
Пример #14
0
        /// <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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        /// <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);
            }
        }
Пример #17
0
        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));
        }
Пример #18
0
        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);
                }
            }
        }
Пример #19
0
        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);
                });
            }
        }
Пример #20
0
        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));
        }
Пример #21
0
        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);
                });
            }
        }
Пример #22
0
        /// <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);
        }
Пример #23
0
        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);
            }
        }