概述
接口平台通过消息服务来通知对接系统数据的变化,避免轮询,这些消息,本质上是业务事件。
例如,对于物流这个业务场景下的交货单,在单据创建、委托下达、车辆进厂、车辆离厂、客户签收等事件产生时,给相关系统推送一条消息,简要通知事件信息,如单据的新增、修改、作废,只需要消息中携带单号和类型即可。
虽然消息服务从技术角度上有能力推送更多的业务数据,但我们从规划设计上,只赋予消息通知轻量级的通知职责,即仅告知数据变化,具体发生了什么变化,相关系统如需要,则可以调用API接口进行数据查询(通常新增和修改需要调用查询,而作废则无需再查询数据),这样设计可以保证关键业务逻辑在API接口中实现,而不是在API和消息服务中重复出现相同或相似的业务逻辑处理。
初步方案
按照上面的设计思路,事件只需要单据标识和状态(或称之为事件描述)即可,将事件作为消息内容,并附加一个消息主题,在生产者、消息服务中心和消费者之间传递。
事件本身很简单,只定义一个包括标识和状态在内的基类即可,暂不考虑根据具体业务事件进行扩展,否则当业务扩展时,服务端增加新的业务事件,需要客户端也同步增加新的业务事件,反而增加耦合度,不如直接用基类来做反序列化和解析来得方便。
/**
* 事件基类
* @author wqliu
* @date 2021-10-5
**/
@Data
public class BaseEvent {
/**
* 标识(实体标识,通常为单据业务编号)
*/
private String id;
/**
* 事件名称
*/
private String name;
}
方案优化
上面的实现本身可以满足我们的需求的,并且是相对规范的实现方式,但实际使用时便利性差一些,主要在于事件与消息主题的关系,这二者实际上在大多数情况下代表的意义是相同的,如果分别定义,一方面繁琐,另一方面,还需要建立对应关系。
因此我们做了变通,约定事件描述与消息主题完全相同,可以极大地简化处理。
例如委托单创建这一事件,我们约定事件编码为:lms.transportbill.consignmentbill.create(系统名+模块名+实体名+动作),当我们的业务应用物流系统发生该事件时,仅需要调用生产者对外的暴露的一个rest接口,把事件编码和单据标识传入即可,然后,生产者直接用这个事件编码作为消息主题,向消息服务中心推送消息,消息内容直接放单据编号就可以了。
也就是说,消息的content属性中,不再需要放一个BaseEvent或其子类序列化后的json字符串了,从而消息中心收到该消息时也不再需要反序列化,通过消息主题完全可以确定应当进行什么样的处理,相当于减少了数据冗余,使逻辑关系更清晰。
以上简化处理可以应对大多数业务情况了,但也并没有影响系统对业务的支持和扩展,一些特殊或复杂的场景,依旧可以往content字段里放json字符串。例如,客户端发起登录请求,这时候一个属性就不够用了,需要账号和密码,这个时候,我们可以往content里放一个json字符串,消息服务中心对应处理就好了,不过依旧没必要使用BaseEvent或其子类。
也就是说,优化后的方案,我们把事件作为抽象概念来处理,不再需要具体的类来对应和实现。
开源平台资料
平台名称:一二三开发平台
简介: 企业级通用低代码开发平台
设计资料:CSDN专栏
开源地址:Gitee
开源协议:MIT
欢迎收藏、点赞、评论,你的支持是我前行的动力。