Skip to content

usiboy/eventcenter-tutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

事件中心教程

事件中心logo

前言

看到这个名字很多人会想到领域驱动开发,俗称DDD。说起领域驱动开发,很多都停留在理论阶段中,平常我们在设计一套系统时候,刚开始的设计都是完好的,随着项目的迭代和反复的用户需求整改,原先设计好的领域对象,系统分层和边界都被破坏掉了,系统中的很多领域逐渐向贫血模型靠拢了。这也从侧面反应了领域设计的难度,主要是很多技术会把领域驱动开发看成是一套单纯的技术工具集,带着这样的理念设计系统,很容易把领域变的臃肿或者是变的单薄。

臃肿既是领域和领域的耦合度太高,没有设计好一个领域强行依赖了多个相关的领域,甚至是不相关的领域。随着项目后期的迭代,导致系统莫名的卡顿,修改一处代码可能会引发更多的Bug。领域模型设计有一套思想和原则,例如单一原则,单一原则的思想要理解透,首先要对业务和建模要有比较深的认知,往往项目在设计的后期会混淆了领域的角色,让儿子承担了父亲的角色,让老板干了员工的事情,甚至会出现本末倒置的问题等等。这样的领域在未来的变化中,举步维艰,难以修改,牵一发则动全身。

单薄的意思对应的是老马(Martin Fowler)提出的四大领域模型中的失血模型和贫血模型,项目在迭代到一定时期之后,随着需求的变更,团队人员的换血,项目进度紧张等因素的影响,往往会让架构师和开发从面向对象设计转变为面向关系型数据库的设计,逐步形成了由下至上的架构方式,这样设计速度快,技术都能理解。于是大家都开始先设计数据表,对象和对象之间的关系完全使用表与表的关系进行描述,业务对象也逐步换成POJO的风格,通过封装业务Service的方法,将多个不同的数据对象聚合在Service层中,导致这个业务领域承担了他所不应该承担的责任。这种模型开发简单,很多技术都能拍脑袋把这个模型设计出来,对于大多数初创团队来说,而且现在大多数技术都是从这种方式开始学习架构和设计WEB,这种设计风格无疑是成本最低的,因为每个技术都能比较容易和直观的理解和接受这种方式。但是,缺点也是显而易见的,产品和技术之间沟通会形成一个障碍,领域模型能够比较直观描述领域的属性和行为,产品对底层技术了解不透,产品需要增加一个功能时,可能会对系统底层有较大的改动,技术会感到恐慌,这种恐慌可能是因为系统的不合理设计,或者是历史遗留问题,或者是臃肿的领域,技术改到一处代码可能会影响到多处的业务,项目长期这样迭代下去,会产生很多不稳定的情况出现。

事件是领域驱动设计中的一种架构方式。它是领域模型间交互的媒介,使两者或者多者之间产生联系,举个例子。

在私营企业内,老板想要做件大事,于是找来两个中层的管理,召开会议,并在会议结束后,分别给两个管理派了任务,要求,在年底要有结果,并在每个季度末需要阶段性汇报成果。两个管理根据老板的任务开始筹划工作,并召集自己的小弟们,讨论内容,设计方案,最后将实施方案指派到各个小弟们手上,并同样严格要求他们要在指定时间内完成指定的内容。工作就这么展开了,每周末,大伙们都会及时汇报工作总结给管理们,管理收到结果也及时的整理进度汇报给老板。突然,有一天,某个小弟因为老婆要生小孩,需要请假一周,成熟稳重的管理及时将任务进行调配,分配给比较闲的人。为了保障项目如期完成,管理会定期的进行询问和关怀,以便保障年底有个好的结果。

老板、管理和小弟们都是领域对象,他们协作中产生的结果可以理解为一个大事件,事是老板的大事,他是具有生命周期,从最初老板的想法开始,就已经萌芽,经过和大家的共事和努力,在年底产出了结果,也就是件。老板收获的结果,是从最底层的任务,不断的向上传递过来,管理层也会定时轮询各个底层,判断状态,控制风险,汇总结果。所以在这个系统(公司)中,领域和领域能够齐心协力、有条不紊的将事情完成下去。

我们都知道,这应该是个合理的工作流程,假如中间少了任务的传递和沟通,就会造成,老板一直等着管理层出结果,管理层也一直等着小弟们赶紧完成工作,于是高层们就这么干等着,啥事也干不了。最头疼的事,老板得记住每个干活的人,少一个人这事都很难进行下去。这样造成了整个公司的业绩产出低下。没了事件,就意味着大伙得依赖在一块,可想而知,这事一件多么痛苦的事情。

那么事件中心是干什么的呢?

什么是事件中心?

  • 如果您正在使用DDD设计系统,其中的领域事件的设计和实现完全可以使用事件中心来代替,在设计上不仅提供了相应的模式,在实现上提供了强大的组件支持,也可以自定义组件,能够和其他消息服务对接,例如RocketMQ、ActiveMQ等等
  • 如果您的系统正在由单体WEB垂直切分成多个模块时,需要设计好系统与系统间的界限上下文,其中系统内的领域的事件可以使用事件中心来完成
  • 如果您需要一个具备高可用,服务自治性强的事件传递中间件,事件中心可以帮助你达到目标

事件中心包含哪些功能?请查看功能介绍

架构

事件中心架构

事件中心的架构是一个去中心化的风格,每个节点都具有独立的事件队列和运行容器,通过发布订阅的方式,将事件以复制的方式冗余到各个消费节点中。对上层提供基于事件驱动的开发能力,对下层隐藏具体的技术细节。除此之外,还可以对接私有的消息队列服务,消息路由机制,实现多种方案的选择。

关于事件的调用链路设计,请查看事件触发机制

事件中心和消息中间件有什么区别?

大多数人会把事件中心看成是一个具体的技术工具,这个看法会比较片面,事件中心的设计理念有点类似Spring框架,Spring最核心的思想是在于他的IOC容器,并随之进行扩张和适配各种强大的组件;事件中心基于领域事件的概念实现了一个功能相对健全的建模工具,同时也提供一套核心的框架,并支持各种技术组件。

如果直接使用消息队列服务作为事件的载体,可能对业务代码产生一定的入侵性,如下是RocketMQ的生产端的代码:

Message msg = new Message("Jodie_topic_1023",
                    "TagA",
                    "OrderID188",
                    "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
producer.send(msg, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
        System.out.printf("%-10d OK %s %n", index, sendResult.getMsgId());
    }

    @Override
    public void onException(Throwable e) {
        System.out.printf("%-10d Exception %s %n", index, e);
        e.printStackTrace();
    }
});

对于事件中心则不需要这么麻烦,如下:

eventcenter.fireEvent(this, "trade.created", "1000001");

如下是基于注解:

class Trade {
    
    /**
    * 注解方式,会自动将方法的参数设置到事件的参数中,并将返回对象设置到result中 
    */
    @EventPoint("trade.created")
    public Trade create(String tid){
        // .....
        return trade;
    }
}

是不是很简单,这完全不需要开发者去关心事件是如何消费、如何传播到消费端的?到了这一层面将会有相应的实现完善事件的传播和可靠性。对于软件设计者来看,能够将更多的时间和注意力放在领域事件的设计层面上,而不需要考虑底层的技术实现。

事件中心提供了容器的接口,可以接入各种消息队列服务,同时事件中心本身也提供了优秀的实现容器,足以应对大型的应用。

About

编写了事件中心使用教程

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published