为什么创业公司反而适合使用微服务+事件溯源? -zimarev


为什么推荐在创业公司中使用eventsourcingdddesign和microservices微服务
在过去的一年中,我参加了很多有关eventsourcing事件溯源的网络研讨会,讲座和讲习班。很多时候观众回答一个问题:什么时候使用这种模式?也就是说:在什么情况下,事件驱动架构(EDA),面向服务的架构(SOA),CQRS等无法适用了?
我通常会告诉人们,当您真的不知道自己在做什么的时候,使用事件溯源可能会引入不必要的复杂性。
 
早期软件版本的质量
任何软件的早期版本都具有许多变通办法:各种黑客和捷径方式。故意接受对质量的这种妥协就是我们所说的技术债务,这意味着需要偿还利息。这种情况在创业公司是正常合理的,一家初创公司可以烧掉投资者的钱,然后开展业务,早期版本的软件可能会破产,然后将债务注销。
牢记这一点,我们可以清楚地看到,花很多时间在软件的技术优势上,甚至可能永远都不会使用,这没有多大意义。
我不会在这里谈论EDA或事件源,因为我不认为应用这些模式从定义上可以使您的软件更好。我想指出的是,领域驱动设计(DDD)并不是真正的软件模式或体系结构,它可以为您节省数月的工作,尤其是在早期阶段。那么,DDD如何提供帮助呢?
假设创业的想法尚未得到正确验证,我们甚至可能不知道我们要解决的问题是否相关。实际上,这就是DDD发光的区域。与您未来的客户(用户)的合作(这些客户在DDD中称为领域专家),可为您的客户带来大量宝贵见解:存在哪些困难以及如何解决他们的问题。与真正的客户进行一些Event Storming会议肯定会改变您对域和提议的解决方案的看法。
话虽如此,我并不是要告诉您使用聚合,存储库或值对象。那不是重点。但是,您将能够以纯粹编写软件和讨论团队内进度的方式来查看,理解和建模系统行为。
实际上,仅通过这样做,就可以避免您的软件最终破产!
设计不良的软件(尤其是在创业环境中)的另一个问题是,第二阶段永远不会实现。原本打算成为技术债务本质上将成为负担,您将没有时间解决。为什么?由于创业公司很少有能力花费时间来巩固他们的系统,因为它们的工程能力有限,需要要花很多钱,而且积压的产品也很厚,报废写得不好的五个版本的软件是完全可以的,因为它不符合目的。当第六版取得成功时,它的编写也将很糟糕,因为我们计划也将其废弃,但最终发现它很有用。
 
创业的事件溯源
有时,我会自己制作小型产品,以摆脱日常工作,并使我的技术和产品技能保持稳定。看起来像是一家初创公司,我敢肯定我的一些同事也会这样做。
曾经,我建立了一个工作系统来支持我的度假物业租赁业务。它是一个整体,它使用文档数据库来实现数据存储的持久性。里面有大量的变通办法、硬编码、常见的hack。
在这种情况下,我也是一个领域专家,因为我确切地知道我想解决什么问题,仅因为这些是我自己的问题。在这方面,我还不能说这是一个干净的实验,因为您很少会从潜在客户那里获得对问题空间的这种了解。尽管如此,足以称呼它为实验室。
 
模型是错误的
之后,我发现我的域模型是错误的。我没有花足够的时间来建模各种场景上下文,只专注于最明显的场景上下文。
当我找到一个更好的模型时,我发现自己被构建的系统所困扰。怎么会这样 仅仅因为我所拥有的只是数据库中的一堆文档,代表了当前的系统状态。由于模型不正确,因此状态本身虽是正确的,但是没有足够的数据。也可以说该模型不是完全错误的,但是它缺少一个重要的上下文,我甚至不知道它为什么存在。
我当时意识到的是今天我清楚记得的事情。我的系统的行为是正确的。我所拥有的所有命令都是有效且有用的。但是,当我使用基于状态的持久性时,我没有明确捕获行为,而是更新了系统状态,因为我们几乎在所有地方都“默认”了。对于新模型,我需要对该行为进行不同的表示,以另一种状态表示。所以,这是我学到的东西:
从行为重构状态非常容易。从某种状态对行为进行逆向工程非常困难,有时甚至是不可能的。
这是状态示例,即MongoDB中的Booking状态:

{
    "_id": "ac2fd0edd2d74f249afea3f9014934ad",
   
"amount": "5600",
   
"bookingChannel": "booking.com",
   
"checkInDate": [{"$numberLong": "637498908000000000"}, 0],
   
"checkOutDate": [{"$numberLong": "637500636000000000"}, 0],
   
"externalBookingNumber": "2955008750",
   
"guest": {
       
"name": "Ole Nordmann",
       
"email": "ole.fake0@brooking.me",
       
"phone": "+78123123123"
    },
   
"paidInFull": false,
   
"prepaid": false,
   
"property": {
       
"_id": "0392c950d8ea4840850d098af0de12df",
       
"name": "Great Apartment"
    }
}

最终发现,当我需要检查一个新预订的可用性时,仅检查该房间将来的所有预订都非常困难。而且,如果您处理房间类别而不是单个房间,则将变得更加困难。我需要一个叫做Day日期的东西,这个概念可以在许多领域中找到,它涉及调度。
如果我的系统从第一天开始就是事件源的,那么我可以删除并重建系统状态,或者通过编写新的读取模型投影非常容易地引入状态的新表示。我可以将它们与当前正在运行的生产系统分开创建,并且仍然使用生产数据,因为它甚至不会影响任何已经可用的数据。
... 

微服务
现在,我想谈一谈SOA。
在我提到的系统中,目前有四个服务:

  • 后台办公
  • 访客门户
  • 讯息传递
  • 日历供稿同步

我将这些子系统拆分为单独的服务的原因非常明显。它们有着完全不同的关注点,尽管其中一些可能是多上下文服务,但我可以清楚地将它们识别为有界的上下文。
我可以将它们全部建成一个整体吗?是的,为什么不?会更容易维护吗?但是我不会。
首先,当其中只有一部分发生更改时,我不想部署整个组件。后台办公服务对我来说是适当的管理者。它具有身份验证和授权位,不适用于任何其他组件。我也随时可以自由部署它,因为它只会影响我。在访客尝试办理登机手续时(或更糟糕的是,在付款会话的中间),可能会部署访客门户网站。在没有适当的部署策略的情况下部署消息服务可能会导致消息丢失,因此我必须始终有至少一个实例在运行。
其次,我觉得在上下文相关的软件上工作会更好。它并不会给我造成太多的认知超负荷,因为我确切地知道它会做什么以及我需要如何做。在整体/单体系统中,我经常发现自己被拖离了最初的任务,因为我开始注意到其他不相关的事物,这些事物我想“顺便”解决。
 
结论
正如我前面提到的,在创业环境中处理事件源,DDD,微服务等可能对您来说不是一件容易的事。如果您没有很多经验,但是又不在一开始创业就这么做,您将永远无法获得这些知识的经验……
随着我更加熟练地应用这些模式,并且对DevOps部分更加满意,我不再担心所谓的意外复杂性。
我一直看到的是:系统是由那些难以集中精力的团队以及不断争论着无休止的依赖关系的团队在没有任何模型的情况下使用整体数据库构建的。
对于我来说,我宁愿构建一个事件源、事件驱动的系统,将其分成几个微服务,尤其是在初创公司中!