# 《分布式IM系统》大后端平台-好友服务-第03节:领域事件的发送与接收设计和实现

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)
课程视频:https://t.zsxq.com/17xmRTYbm (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本节难度:★★☆☆☆
  • 本节重点:对大后端平台中好友微服务领域事件的设计发送与接收进行设计和实现,掌握异步处理领域事件的落地方案与实现技巧,掌握在DDD领域架构模式下,采用Cola框架与RocketMQ发送并接收领域事件的方法,并能够将其灵活应用到自身实际项目中。
  • 课程视频:https://t.zsxq.com/17xmRTYbm (opens new window)

大家好,我是冰河~~

在大后端平台的好友微服务中,用户添加好友、删除好友和修改好友备注信息时,会对外发布一个领域事件,具体的业务方法会立即返回。由单独的领域服务监听对应的事件,接收到事件后,去更新分布式缓存中的数据。

# 一、前言

在大后台平台的好友微服务中,获取好友信息时,会将先从分布式缓存中查询数据,如果缓存中不存在数据,则获取分布式锁,同一时刻只允许一个线程查询数据库中对应的数据,随后将数据保存在分布式缓存并返回。

可以看出,数据是会同步到缓存的,那如果用户添加好友、删除好友、修改好友的备注信息时,该如何处理呢?此时,可以在领域层操作完数据库数据后,对外发布一个领域实现,由应用层监听领域事件,接收到数据后,更新分布式缓存数据,这样即达到了解耦的目的,又增强了系统的吞吐量,提供了系统的整体性能。

# 二、本节诉求

对大后端平台中好友微服务领域事件的发送与接收进行设计和实现,掌握异步处理领域事件的落地方案与实现技巧,掌握在DDD领域架构模式下,采用Cola框架与RocketMQ发送并接收领域事件的方法,并能够将其灵活应用到自身实际项目中。

# 三、流程设计

在好友微服务中,当领域层执行完修改数据库中数据的逻辑后,可以对外发布一个领域事件,由应用层订阅相关的领域事件,当应用层接收到领域事件后,异步处理分布式缓存中的数据,整体流程如图3-1所示。


可以看到,更新完好友数据库中的数据后,领域层会将事件封装成对应的事件模型发布出去,至于是发布到Cola,还是发布到RocketMQ,完全由配置决定,后续不需要修改代码即可实现。而应用层会监听并接收Cola或者RocketMQ中的事件,并更新分布式缓存中的好友数据。

同时,不管是将事件发布到Cola还是发布到RocketMQ,统一实现了对应的事件模型,而不必单独为每种事件的发布方式单独设计事件模型,体现了事件模型在设计上的通用性和高度可扩展性。

# 四、编码实现

具体的实现步骤如下所示。

(1)修改FriendDomainServiceImpl类

主要是修改FriendDomainServiceImpl类中绑定好友、解除绑定好友、修改好友信息的方法,处理完数据库数据后,新增对外发布领域事件的方法。

源码详见:bh-im-platform-friend-domain工程下的io.binghe.im.platform.friend.domain.service.impl.FriendDomainServiceImpl。

@Autowired
private MessageEventSenderService messageEventSenderService;

@Value("${message.mq.event.type}")
private String eventType;

@Override
public void bindFriend(FriendCommand friendCommand, String headImg, String nickName) {
    /**********省略其他代码************/
    if (result){
        //发布领域事件
        IMFriendEvent friendEvent = new IMFriendEvent(friendCommand.getUserId(), friendCommand.getFriendId(), IMPlatformConstants.FRIEND_HANDLER_BIND, this.getTopicEvent());
        messageEventSenderService.send(friendEvent);
    }
}

@Override
public void unbindFriend(FriendCommand friendCommand) {
    /**********省略其他代码************/
    if (count > 0){
        //发布领域事件
        IMFriendEvent friendEvent = new IMFriendEvent(friendCommand.getUserId(), friendCommand.getFriendId(), IMPlatformConstants.FRIEND_HANDLER_UNBIND, this.getTopicEvent());
        messageEventSenderService.send(friendEvent);
    }
}

@Override
public void update(FriendVO vo, Long userId) {
   /**********省略其他代码************/
    if (count > 0){
        //发布领域事件
        IMFriendEvent friendEvent = new IMFriendEvent(userId, vo.getId(), IMPlatformConstants.FRIEND_HANDLER_UPDATE, this.getTopicEvent());
        messageEventSenderService.send(friendEvent);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 查看完整文章

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码