套路

单例模式 连接

  public interface IRabbitMqConnection
  {
      IConnection Connection { get; }
  }
  public class RabbitMqConnection : IRabbitMqConnection
  {
      private static RabbitMqConnection rabbitMqConnection;
      private ILogger<dynamic> _logger = default!;
      private volatile static object lockRabbitCon = new object();
      public IConnection Connection { get; private set; } = default!;

      private RabbitMqConnection() { }

      /// <summary>
      /// 私有构造函数
      /// </summary>
      /// <param name="options"></param>
      /// <param name="clientProvidedName"></param>
      /// <param name="logger"></param>
      private RabbitMqConnection(RabbitMqOptions options, string clientProvidedName, ILogger<dynamic> logger)
      {
          _logger = logger;
          ConnectionFactory factory = new ConnectionFactory()
          {
              HostName = options.HostName,
              Port = options.Port,
              UserName = options.UserName,
              Password = options.Password,
              VirtualHost = options.VirtualHost,
              AutomaticRecoveryEnabled = true
          };
          Connection = factory.CreateConnection();

          Policy.Handle<SocketException>().WaitAndRetry(retryCount: 3,
                       count => TimeSpan.FromSeconds(1), (ex, time, retryCount, content) =>
                       {
                           if (retryCount == 3)
                           {
                               _logger.LogWarning($"{ex.Message}");
                               throw ex;
                           }

                       }).Execute(() =>
                       {
                           rabbitMqConnection.Connection = factory.CreateConnection();
                       });
      }
      public static RabbitMqConnection Instance(RabbitMqOptions options, string clientProvidedName, ILogger<dynamic> logger)
      {
          if (rabbitMqConnection == null)
          {
              lock (lockRabbitCon)
              {
                  if (rabbitMqConnection == null)
                  {
                      rabbitMqConnection = new RabbitMqConnection(options, clientProvidedName, logger);
                  }
              }
          }
          return rabbitMqConnection;
      }

  }

  

 

 

Hostservice 抽象类 继承

  public abstract class KafkaConsumerHostService : IHostedService
  {
      protected readonly IOptions<KafkaConfig> _options;
      private readonly IKafkaConsumerPrivoder _consumerFactory;
      IConsumer<string, byte[]> consumer;
      protected KafkaConsumerHostService(IKafkaConsumerPrivoder consumerFactory, IOptions<KafkaConfig> options)
      {
          _options = options ?? throw new ArgumentNullException(nameof(options));
          _consumerFactory = consumerFactory;
      }

      /// <summary>
      /// 获取消费者配置
      /// </summary>
      /// <returns></returns>
      protected abstract ConsumerConfig GetConsumerConfig();
      /// <summary>
      /// 获取消费绑定主题
      /// </summary>
      /// <returns></returns>
      public abstract List<string> GetTopic();
      /// <summary>
      /// 消费者处理
      /// </summary>
      /// <param name="result"></param>
      public abstract void Process(ConsumeResult<string, byte[]> result);
      public Task StartAsync(CancellationToken cancellationToken)
      {
          ConsumerConfig config = GetConsumerConfig();
          consumer = _consumerFactory.GetConsumer(config);
          // 订阅 生产者的主题
          consumer.Subscribe(GetTopic());
          Task task = Task.Factory.StartNew(() =>
          {
              while (true)
              {
                  try
                  {
                      var consumeResult = consumer.Consume(cancellationToken);
                      if (consumeResult.IsPartitionEOF)
                      {
                          Console.WriteLine($"Reached end of topic {consumeResult.Topic}, partition {consumeResult.Partition}, offset {consumeResult.Offset}.");
                          continue;
                      }
                      if (consumeResult is not null)
                      {
                          Process(consumeResult);
                      }
                      try
                      {
                          consumer.StoreOffset(consumeResult);
                      }
                      catch (KafkaException e)
                      {
                          Console.WriteLine($"Store Offset error: {e.Error.Reason}");
                      }
                  }
                  catch (System.AccessViolationException e)
                  {
                      Console.WriteLine($"{e.Message}");
                  }
                  catch (ConsumeException e)
                  {
                      Console.WriteLine($"Consume error: {e.Error.Reason}");
                  }
              }

          }, TaskCreationOptions.LongRunning);
          task.ConfigureAwait(false).GetAwaiter();
          return Task.CompletedTask;
      }

      public Task StopAsync(CancellationToken cancellationToken)
      {
          consumer?.Close();
          consumer?.Dispose();
          return Task.CompletedTask;
      }
  }

  public class KafkaConsumerHostService1 : KafkaConsumerHostService
  {
      public KafkaConsumerHostService1(IKafkaConsumerPrivoder consumerFactory, IOptions<KafkaConfig> options) : base(consumerFactory, options)
      {
      }

      protected override ConsumerConfig GetConsumerConfig()
      {
          return new ConsumerConfig
          {
              BootstrapServers = _options.Value.BootstrapServers,
              AutoOffsetReset = AutoOffsetReset.Latest,
              GroupId = "order-yanchi",
              EnableAutoCommit = false,
              EnableAutoOffsetStore = false,

          //    producerConfig.MessageTimeoutMs = 5000;//失败重试时间
          //producerConfig.EnableIdempotence = true;//幂等性:如果生产者发送失败不重复发消息失败重试
          //producerConfig.SaslUsername = "";//用户名称
          //producerConfig.SslKeyPassword = "";//密码
          //                                   // Fixed properties
          //producerConfig.SecurityProtocol = SecurityProtocol.SaslSsl;
          //producerConfig.SaslMechanism = SaslMechanism.Plain;
          //producerConfig.Acks = Acks.All;
      };
      }
      public override List<string> GetTopic()
      {
          return new() { "order" };
      }

      public override void Process(ConsumeResult<string, byte[]> result)
      {
          byte[] bytes = result.Message.Value;
          string str = Encoding.UTF8.GetString(bytes);
          Console.WriteLine($"最新的:{str}");
      }

  }

  public class KafkaConsumerHostService2 : KafkaConsumerHostService
  {
      public KafkaConsumerHostService2(IKafkaConsumerPrivoder consumerFactory, IOptions<KafkaConfig> options) : base(consumerFactory, options)
      {
      }

      protected override ConsumerConfig GetConsumerConfig()
      {
          return new ConsumerConfig
          {
              BootstrapServers = _options.Value.BootstrapServers,
              AutoOffsetReset = AutoOffsetReset.Latest,
              GroupId = "order-yanchi1",
              EnableAutoCommit = false,
              EnableAutoOffsetStore = false,

          };
      }
      public override List<string> GetTopic()
      {
          return new() { "order" };
      }

      public override void Process(ConsumeResult<string, byte[]> result)
      {
          byte[] bytes = result.Message.Value;
          string str = Encoding.UTF8.GetString(bytes);
          Console.WriteLine($"最新的11:{str}");
      }

  }

 

hostservice批量注入 通过程序集查找实现子类  原理 因为 hostserivce 是添加 集合然后 .net core 调用 所以直接单例模式注入就行  services.AddSingleton(typeof(IHostedService), item);

        public static IServiceCollection AddKafkaConsumer(this IServiceCollection services, IConfigurationSection kafkaSection)
        {
            services.Configure<KafkaConfig>(kafkaSection);
            services.AddSingleton<IKafkaConsumerPrivoder, KafkaConsumerPrivoder>();
            Type typeBase = typeof(KafkaConsumerHostService);
            //批量注入 hostservice
            var implTypes = Assembly.GetEntryAssembly().ExportedTypes.Where(item => item.BaseType == typeBase && item.IsClass).ToList();
            foreach (var item in implTypes)
            {
                services.AddSingleton(typeof(IHostedService), item);
            }
            return services;
        }

  

 

 

单例模式注入

        public static IServiceCollection AddKafkaProduce(this IServiceCollection services, IConfigurationSection kafkaSection)
        {
            services.Configure<KafkaConfig>(kafkaSection);
            services.AddSingleton<IKafkaProduce>(sp =>
            {
                KafkaConfig kafkaConfig = sp.GetRequiredService<IOptions<KafkaConfig>>().Value;
                return KafkaProduce.CreateInstance(config =>
                 {
                     config.BootstrapServers = kafkaConfig.BootstrapServers;
                     config.MessageTimeoutMs = 5000;//失败重试时间
                     config.EnableIdempotence = true;//幂等性:如果生产者发送失败不重复发消息失败重试
                 });
            });
            return services;
        }

  

  

 

posted on 2024-07-30 17:58  是水饺不是水饺  阅读(7)  评论(0)    收藏  举报

导航