[经验分享] OpenHarmony 事件通知子系统机制介绍

深开鸿_王肖云 显示全部楼层 发表于 2023-10-30 09:40:58
作者:王肖云
1 简介
该系统实际是由两个子系统组成:事件子系统(CES)和通知子系统(ANS)。OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力,通过ANS(Advanced Notification Service,即通知增强服务)系统服务来为应用程序提供发布通知的能力。这两个子系统均采用了订阅机制,是一种基于消息发布和订阅的事件驱动机制,即事件/通知发布者负责发布消息,而消息接收者需要先订阅事件/通知,然后才能收到消息。事件和通知子系统为消息注册中心,并提供了消息订阅/退订和消息发布的接口,作为应用或其它系统组件,只需要根据这两个子系统提供的接口,即可进行事件/通知的发布、订阅或退订。
CES和ANS两者机制一样,只是业务稍有差异,本文以下内容均以事件子系统(CES)进行介绍。
先介绍几个概念。
  • 有序事件:有序事件中的“有序”是针对事件订阅者而言的,指的是发送出去的事件被订阅者按照先后顺序接收,因为订阅者订阅事件时会指定订阅者自身的优先级。简而言之“有序”并非n个事件之间的排序,而是针对同一事件的众多订阅者之间的顺序。
  • 无序事件:同一事件的多个订阅者之间没有接收顺序之分,同一事件可向多个订阅者同时并行发送。
  • 粘性事件:在订阅的事件已经发送后,再订阅该事件的其它订阅者也能收到该事件。

2 系统分析2.1 事件子系统关键组件消息交互分析
fakename.png
    图 2 关键组件消息交互
事件子系统由三个角色组成:发布者(Publisher)、订阅者(Subscriber)和注册中心(CES Manager),三个角色可能都位于不同的进程,他们之间通过OpenHarmony系统提供的IPC机制进行通信。IPC通信采用了一种跨进程的代理模式,即Proxy-Stub模式,该模式中有两种角色Client和Server。Client端通过持有远端对象的代理(Proxy),调用代理的接口即可与远端对象进行通信,远端对象通过存桩(Stub)即可接收到Client端发送的消息。消息都是由客户端发起,服务端Stub中用相同的接口进行接收。
对应上图可以看到,事件的发布者和订阅者是IPC通信中的Client角色,事件订阅者(发布订阅动作)同时也是事件广播的接收者(接收系统广播的事件),既充当了Client角色又充当了Server角色,因为IPC通信中通信发起方只能是Client。既然IPC通信只能由Client端发起,那作为订阅者只能是发起方,那又怎样接收消息呢?
此处设计的巧妙之处就在于类CommonEventListenner继承了EventReceiveStub, 同时该类中又包含了订阅者的信息(CommonEventSubscriber)。继承EventReceiveStub,就可以作为Server进行事件广播的接收,同时因为持有订阅者信息,就可以向订阅者进行消息发送,这样一来就可以实现订阅者对消息的接收和发送了。实质就是利用IPC通信机制实现了跨进程的观察者模式。
上图右侧框图中大家注意到,实际系统中有序事件的线程实例(OrderedEventHandler)只有一个,而无序事件的线程实例(EventHandler)可以是任意个,这其实对应前面概念中的有序事件和无序事件,因为有序事件是对相同事件需要按订阅者的顺序进行发送,所以只能有一个线程,在此线程中根据订阅者的优先级进行依次广播,只有收到优先级高的订阅者的应答才会继续进行下一个订阅者的事件广播。而无序事件,因订阅者对事件接收顺序是不关心的。
2.2 订阅流程
fakename.png
图 3 订阅流程调用关系图
如图,虚线上部分是订阅者调用订阅接口时CES的处理流程,虚线下部分是CES Server接收到订阅消息的处理流程,虚线处的向下箭头代表了IPC通信。 仔细看该图最下面绿色方框的内容:PublishStickyEvent,发布粘性事件。订阅者信息插入成功后,系统就会将之前已经发送过的事件向该新订阅者进行发送,其实这也就是此处体现了粘性事件的实现机制。
2.2 事件发布流程
fakename.png
图 4 事件发布流程调用关系图
如图,虚线上部分是事件发布者调用发布接口时CES的处理流程,虚线下部分是CES Server接收到事件后的处理流程,虚线处的向下箭头代表了IPC通信。事件发布流程经由的类其实跟订阅流程经由的类差不多。
2.3 类关系
fakename.png
图 6 类图
上图列出了事件子系统中的主要类及其之间的调用、依赖关系,下面给出各关键类的描述。 主要类的功能:
  • CommonEventManagerService:该类继承了SystemAbility,实现了OnStart方法,为整个事件子系统的入口。
  • CommonEventManager:对消息进行整合后,通过获取CommonEvent实例,调用CommonEvent中同名的接口方法。
  • CommonEvent:该类获取并持有远端通信对象的ICommonEventProxy代理,提供了发布公共事件、创建订阅者、订阅、取消订阅等的接口。
  • InnerCommonEventManager:该类是在有序事件处理和无序事件处理的上层,提供了统一的接口,屏蔽了不同事件的处理差异。
  • ICommonEvent: 继承自IRemoteBroker的接口类,定义了发布、订阅、退订的接口。
  • CommonEventProxy:继承至IRemoteProxy,参数序列化处理后通过远端对象的接口调用(remote->SendRequest)实现ICommonEvent中定义的接口方法。
  • CommonEventStub:继承至IRemoteStub ,实现OnRemoteRequest方法和ICommonEvent中定义的接口方法。
  • IEventReceive:继承自IRemoteBroker的接口类,定义了事件广播的接口。
  • EventReceiveProxy:继承至IRemoteProxy,参数序列化处理后通过远端对象的接口调用(remote->SendRequest)实现IEventReceive中定义的事件广播接口。
  • EventReceiveStub:继承至IRemoteStub,实现OnRemoteRequest方法和IEventReceive中定义的广播接口。
  • CommonEventSubscriber:事件订阅者,用于获取所接受公共事件的相关信息,及设定公共事件的处理信息。
  • CommonEventSubscriberManager:该类为单例模式,提供了对订阅者的查询、增加和删除操作。
  • CommonEventListener:该类是整个事件子系统闭环的关键,继承了EventReceiveStub,因此可以收到事件的广播,同时因为持有观察者的信息,收到系统的事件广播消息后可以对所有订阅者进行事件的发送。
总结
本文主要介绍了事件子系统的关键实现机制、主要类关系及重要的处理流程,为开发人员维护和扩展功能提供参考。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部