簡體   English   中英

ASP.Net Core 中的工廠模式

[英]Factory Pattern in ASP.Net Core

我正在Worker Service in .Net Core並為其添加了 DDD。 在應用層,我創建了一個工廠模式來選擇一個特定的消息處理程序來處理不同的 Kafka 主題。 這種方法運行良好。 但是,想知道這是實現它的正確方法嗎? 我對在MessageFactory中注入構造函數參數有點困惑

public interface IMessageFactory
{
    IMessageHandler CreateMessage(string topicName);
}

工廠方法的實現

public class MessageFactory: IMessageFactory
    {
        private readonly ILogger<MessageFactory> _logger;
        private readonly IOneRepository _oneRepository;
        private readonly ITwoRepository _twoRepositoty;

        public MessageFactory(ILogger<MessageFactory> logger,
            IOneRepository oneRepository,
            ITwoRepository twoRepositoty)
        {
            _logger = logger;
            _oneRepository = oneRepository;
            _twoRepositoty = twoRepositoty;
        }

        public IMessageHandler CreateMessage(string topicName)
        {
            switch (topicName.ToUpper())
            {
                case KafkaConstants.OneMaster:
                    return new OneMessageHandler(_logger, _oneRepository );
                case KafkaConstants.TwoMaster:
                    return new TwoMessageHandler(_logger, _twoRepositoty );
                default:
                    return null;
            }
        }
    }
}

個人處理程序

public class OneMessageHandler : IMessageHandler
{
    private readonly ILogger<MessageFactory> _logger;
    private readonly IOneRepository _oneRepository;

    public OneMessageHandler (ILogger<MessageFactory> logger,
        IOneRepository _oneRepository)
    {
        _logger = logger;
       _oneRepository = oneRepository;
    }

    public async Task<bool> ProcessMessage(string message)
    {
        ..........
    }
}

public class TwoMessageHandler : IMessageHandler
{
    private readonly ILogger<MessageFactory> _logger;
    private readonly ITwoRepository _twoRepository;

    public TwoMessageHandler(ILogger<MessageFactory> logger,
        ITwoRepository twoRepository)
    {
        _logger = logger;
        _twoRepository = twoRepository;
    }

    public async Task<bool> ProcessMessage(string message)
    {
        ..........
    }
}

工人服務

public class Worker: BackgroundService
{
    private readonly IMessageFactory _messageFactory;
   
    public Worker(IMessageFactory messageFactory)
    {
        _messageFactory = messageFactory;
    }
    IMessageHandler messageHandler = _messageFactory.CreateMessage("OneMaster");
    messageHandler.ProcessMessage(message_from_kafka_response));
}

依賴注入

services.AddTransient<IMessageFactory, MessageFactory>();

好吧,我會讓所有東西都可注入,所以我可以像這樣注冊它(所有類都自我解釋),而不使用工廠,只使用容器:

container.RegisterSingleton<IHostedService>(x =>
    new RepeatBackgroundWorker(
        repeatInterval,
        new MessageHandler<TKey, TPayload>( //this can also be just something like void IWorker.RunAsync(cancellationToken)
            new KafkaMessageProducer<TKey, TPayload>(/*settings like name, consumer group and connection settings*/),
            x.GetByKey<IMessageProcessor<TKey, TPayload>>(/*processor name*/))));


//RepeatBackgroundWorker - it will generally repeat some background worker
//MessageHandler - it will consume message, process it, set new offset and until message producer enumerable reaches the end (end of queue)
//KafkaMessageProducer - it will just return something like IAsyncEnumerable<Message<TKey, TPayload>>
//IMessageProcessor - it will be your processor

如您所見,您有多種好處:

  • 還可以將任何部分包裝到通用日志記錄或度量系統中,例如 MessageProcessorLogger、MessageProducerLogger 等
  • 可以對生產者應用一般過濾(如按 Key 或有效負載中的某些字段分組,例如:按 UserId 分組消息並采取最后執行的操作,或將其包裝到某個批處理包裝器中等)
  • 可以操縱處理程序的行為(如何以及何時重新啟動,如何處理錯誤等)
  • 可以操縱各種來源(例如,將 kafka 更改為 rabbitmq 等)
  • 可以將整個工廠放入容器或運行時
  • 易於在測試中使用,將生產者更改為某些自定義實現,或用某些東西模擬處理器/消費者
  • 這樣你基本上只需要實現一個處理器/消費者並指定隊列的名稱(kafka的+消費者組),它會自動為你提供命名良好的指標和日志

PS我沒有實現所有類,因為它取決於業務需求

PS2這基本上是我在生產中使用來擠壓 kafka 性能,將所有日志放入 kibana 和所有指標(當您遇到峰值並想要重新平衡向上/向下時,消息時間戳特別有用)從所有來源到 prometheus+grafana盒子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM