套路
单例模式 连接
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;
}
浙公网安备 33010602011771号