ENode架構初始化

來源:互聯網
上載者:User

標籤:

ENode架構初始化前言

Conference案例是使用ENode架構來開發的。之前我沒有介紹過ENode架構是如何啟動的,以及啟動時要注意的一些點,估計很多人對ENode架構的初始化這一塊感覺很複雜,一頭霧水。所以,本文想簡單介紹一下在做一個實際項目時,我們該如何初始化ENode。

使用ENode開發的項目的頂層宿主工程一般有兩類:1)前台Web項目,它的職責就是發送命令;2)後台ProcessorHost項目,負責處理命令或事件;

這兩類項目的初始化方式完全一樣,只是Web項目可能需要多初始化Controller的容器管理。下面我們看看使用ENode架構時的主要初始化邏輯:

private static void InitializeECommon(){    _ecommonConfiguration = ECommonConfiguration        .Create()        .UseAutofac()        .RegisterCommonComponents()        .UseLog4Net()        .UseJsonNet()        .RegisterUnhandledExceptionHandler();    _logger = ObjectContainer.Resolve<ILoggerFactory>().Create(typeof(Bootstrap).FullName);    _logger.Info("ECommon initialized.");}private static void InitializeENode(){    ConfigSettings.Initialize();    var assemblies = new[]    {        Assembly.Load("Conference.Common"),        Assembly.Load("Registration.Domain"),        Assembly.Load("Registration.CommandHandlers"),        Assembly.Load("Registration.ProcessManagers"),        Assembly.Load("Registration.ReadModel"),        Assembly.Load("Registration.ProcessorHost")    };    var setting = new ConfigurationSetting    {        SqlServerDefaultConnectionString = ConfigSettings.ConferenceENodeConnectionString    };    _enodeConfiguration = _ecommonConfiguration        .CreateENode(setting)        .RegisterENodeComponents()        .RegisterBusinessComponents(assemblies)        .RegisterAllTypeCodes()        .UseSqlServerLockService()        .UseSqlServerCommandStore()        .UseSqlServerEventStore()        .UseSqlServerSequenceMessagePublishedVersionStore()        .UseSqlServerMessageHandleRecordStore()        .UseEQueue()        .InitializeBusinessAssemblies(assemblies);    _logger.Info("ENode initialized.");}

從上面的代碼可以看到,ENode架構的初始化是採用FluentAPI的方式,通過使用富有語義的方法來表達當前在做什麼配置。

ECommon初始化

配置ENode一般是分為兩個階段,先配置ECommon。ECommon的初始化邏輯比較簡單,Create方法建立一個ECommonConfiguration類的執行個體,然後通過調用UseAutofac方法,告訴架構當前使用的是Autofac容器。 然後RegisterCommonComponents就是把一些預設的組件注入到容器中;然後UseLog4Net和UseJsonNet這兩個方法就是告訴架構當前使用的日誌組件是Log4Net,JSON序列化組件是JSON.NET。最後,RegisterUnhandledExceptionHandler方法就是告訴架構要捕獲未處理的異常,這樣架構在發現有未處理的異常時,會嘗試記錄錯誤記錄檔。上面的一個配置的兩點是,ENode並沒有和特定的容器綁定,目前僅實現了Autofac,大家可以根據自己的喜好使用其他的IoC容器,比如Untity, Castle, StructureMap等。

ENode初始化

ECommon初始化完成後,開始初始化ENode架構了。ENode的初始化稍微複雜一點,但因為也是通過富有語義的FluentAPI來實現初始化,所以看起來也比較容易理解。

基本配置

我們先建立ENodeConfiguration的全域執行個體,然後同樣註冊ENode的所有預設實現組件以及給定程式集中的所有標記了Component特性的組件到容器。

類型和Code的映射配置

然後接下來就是通過RegisterAllTypeCodes方法告訴架構所有可能涉及到序列化的類的Code。為什麼要做這個配置?因為假如一個Command要發送到訊息佇列,在Command發送時,會用JSON序列化;在Command消費者消費時會用JSON還原序列化。如果我們不設計這種Code機制,那序列化的JSON字串裡需要包含類型的名稱。而我們的類名可能會調整的。所以為了更好的靈活性,我為ENode架構所有可能需要序列化的地方,都通過這種Code的思想,把類型轉換為Code;還原序列化時,根據Code找到對應的類型,然後進行還原序列化;該方法的內部實現大概如下面這樣:

public static ENodeConfiguration RegisterAllTypeCodes(this ENodeConfiguration enodeConfiguration){    var provider = ObjectContainer.Resolve<ITypeCodeProvider>() as DefaultTypeCodeProvider;    //aggregates    provider.RegisterType<Order>(120);    provider.RegisterType<OrderSeatAssignments>(121);    //commands    provider.RegisterType<MakeSeatReservation>(207);    provider.RegisterType<CommitSeatReservation>(208);    provider.RegisterType<CancelSeatReservation>(209);
持久化相關實作類別的配置

由於真實的項目,我們肯定需要做各種持久化,比如事件的持久化,事件處理記錄的持久化等。所以通過上面代碼中的各種UseSql打頭的方法,就可以配置各種情境的持久化實現。然後這些Sql的實作類別所使用的資料庫連接,上面的例子都是使用預設的資料庫連接,見上面SqlServerDefaultConnectionString屬性的賦值。如果你只是想運行一下基於記憶體的模型,那這些UseSql的方法是不需要調用的。比如像ENode架構裡內建的一些例子的配置都很簡單,以NoteSample為例:

static void InitializeENodeFramework(){    var assemblies = new[]    {        Assembly.Load("NoteSample.Domain"),        Assembly.Load("NoteSample.Commands"),        Assembly.Load("NoteSample.CommandHandlers"),        Assembly.GetExecutingAssembly()    };    _configuration = Configuration        .Create()        .UseAutofac()        .RegisterCommonComponents()        .UseLog4Net()        .UseJsonNet()        .RegisterUnhandledExceptionHandler()        .CreateENode()        .RegisterENodeComponents()        .RegisterBusinessComponents(assemblies)        .RegisterAllTypeCodes()        .UseEQueue()        .InitializeBusinessAssemblies(assemblies)        .StartEQueue();    Console.WriteLine(string.Empty);    _logger = ObjectContainer.Resolve<ILoggerFactory>().Create(typeof(Program).Name);    _logger.Info("ENode started...");}
EQueue相關配置

因為ENode需要使用EQueue這個分布式訊息佇列來實現命令或事件的發布和訂閱。所以,我們也需要配置EQueue。通過調用UseEQueue實現,該方法的內部實現需要根據當前伺服器所需要使用的功能而定。

類似於像下面這樣:

public static ENodeConfiguration UseEQueue(this ENodeConfiguration enodeConfiguration){    var configuration = enodeConfiguration.GetCommonConfiguration();    configuration.RegisterEQueueComponents();    var producerEndpoint = new IPEndPoint(SocketUtils.GetLocalIPV4(), ConfigSettings.BrokerProducerPort);    var consumerEndpoint = new IPEndPoint(SocketUtils.GetLocalIPV4(), ConfigSettings.BrokerConsumerPort);    var producerSetting = new ProducerSetting { BrokerProducerIPEndPoint = producerEndpoint };    var consumerSetting = new ConsumerSetting { BrokerConsumerIPEndPoint = consumerEndpoint };    _applicationMessagePublisher = new ApplicationMessagePublisher("PaymentsApplicationMessagePublisher", producerSetting);    _domainEventPublisher = new DomainEventPublisher("PaymentsDomainEventPublisher", producerSetting);    configuration.SetDefault<IMessagePublisher<IApplicationMessage>, ApplicationMessagePublisher>(_applicationMessagePublisher);    configuration.SetDefault<IMessagePublisher<DomainEventStreamMessage>, DomainEventPublisher>(_domainEventPublisher);    _commandConsumer = new CommandConsumer(        "PaymentCommandConsumer",        "PaymentCommandConsumerGroup",        consumerSetting)    .Subscribe(Topics.PaymentCommandTopic);    _eventConsumer = new DomainEventConsumer(        "PaymentEventConsumer",        "PaymentEventConsumerGroup",        consumerSetting)    .Subscribe(Topics.PaymentDomainEventTopic);    return enodeConfiguration;}

使用ENode架構開發的應用,可能會用到如下的角色:

  1. 發送命令,使用CommandService;
  2. 發送領域事件,使用DomainEventPublisher;
  3. 發送應用程式層訊息,使用ApplicationMessagePublisher;
  4. 發送異常,使用PublishableExceptionPublisher;
  5. 消費命令,使用CommandConsumer;
  6. 消費領域事件,DomainEventConsumer;
  7. 消費應用程式層訊息,使用ApplicationMessageConsumer;
  8. 消費異常,使用PublishableExceptionConsumer;

從上面的8個角色中,我們可以知道,主要分為兩類:1)訊息生產者;2)訊息消費者;前面4個是訊息生產者;後面4個屬於訊息消費者;然後生產者內部就是封裝了EQueue的Producer;消費者內部就是封裝了EQueue的Consumer;是不是很對稱,呵呵。

然後一般一個Web工程,它只需要發送命令即可,所以一般只需要初始化CommandService即可;而一般一個ProcessorHost工程,因為可能要處理命令、事件、應用程式層訊息,以及異常訊息。且因為可能有Saga流程的存在,所以它們可能需要配置所有上面8個角色。具體需要配置哪些角色,還是要看具體的應用而定。

當我們執行個體化好了需要的角色後,我們就可以啟動或者關閉它們了。代碼類似如下:

public static ENodeConfiguration StartEQueue(this ENodeConfiguration enodeConfiguration){    _applicationMessageConsumer.Start();    _eventConsumer.Start();    _commandConsumer.Start();    _domainEventPublisher.Start();    _commandService.Start();    return enodeConfiguration;}public static ENodeConfiguration ShutdownEQueue(this ENodeConfiguration enodeConfiguration){    _commandService.Shutdown();    _domainEventPublisher.Shutdown();    _commandConsumer.Shutdown();    _eventConsumer.Shutdown();    _applicationMessageConsumer.Shutdown();    return enodeConfiguration;}
關於Controller所依賴的服務如何注入

上面介紹了ENode架構的主要配置如何使用,但還有一種情境沒有介紹。就是ASP.NET MVC Web項目,Controller往往也是需要讓容器來管理執行個體的。那這個如何配置呢?其實也很簡單。我們只需要在ENode架構配置完成後,在通過如下的代碼就可以實現Controller的生命週期的管理了。

private void RegisterControllers(){    var webAssembly = Assembly.GetExecutingAssembly();    var container = (ObjectContainer.Current as AutofacObjectContainer).Container;    var builder = new ContainerBuilder();    builder.RegisterControllers(webAssembly);    builder.Update(container);    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));}

上面的代碼中,關注點是:AutofacDependencyResolver這個類,這個類是Autofac.Integration.Mvc這個組件提供的。這個組件是Autofac和MVC整合的一個組件。通過它,我們可以方便的實現對Controller的依賴注入。

結束語

好了,基本介紹了一下ENode架構的配置部分如何使用。是不是很複雜?呵呵,其實只要我寫的這些例子你看多了,也是很簡單的,大家做項目時參考我的案例中的寫法即可。

 分類: DDD 案例分析

ENode架構初始化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.