设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

在ModeShape 4.0的事件使用循环缓冲区

2014-9-17 09:39| 发布者: joejoe0332| 查看: 3913| 评论: 0|原作者: 几点人, 无若, AndyLam, 赵亮-碧海情天, it瞌睡虫|来自: 开源中国社区

摘要: 事件对于ModeShape至关重要。当你的应用保存一些变更到页面,ModeShape就会 产生描述那些变更的事件,并且会发送那些事件到你所有的被注册的应用侦听器中。不管哪些集群产生的这些变化或是集群中你的侦听器在哪一部 ...

  事件对于ModeShape至关重要。当你的应用保存一些变更到页面,ModeShape就会产生描述那些变更的事件,并且会发送那些事件到你所有的被注册的应用侦听器中。不管哪些集群产生的这些变化或是集群中你的侦听器在哪一部分所监听到的,都要保证每个侦听器尽可能侦听到所有更改的事件。


  但是你的应用不能仅仅只是对事件做出反应:ModeShape它自己有相当一些侦听器被允许监听和反馈那些一致的更改。许多ModeShape的侦听器在你的页面内回应那些变更,同时另外的内置侦听器也会通过ModeShape回复那些变更。怎么做到的呢?ModeShape在它的存储区域(命名空间,节点类型的定义,锁,版本,索引定义,联合规划(federated projections)等等)存储了各种类型系统的元数据。当任何的元数据被改变并且存留在集群的一个进程中,它仅会通过事件将这些变更通知到这个集群中的另外一些进程。


  例如,当你的应用注册一个新的命名空间prefix/URI对时,ModeShape反射在本地命名空间(NamespaceRegistry)并注册实例至内存中的cache并且立即启动持续信息(的转发)。但是命名空间(NamespaceRegistry)的实例在其他的集群中怎么样呢?他们使用侦听器去查看在命名空间区域内系统元数据的变更,并且他们能立即观察到一个事件描述的新命名空间,(远程)命名空间(NamespaceRegistry)实例能立即更新他们的在内存中的cache,因此所有的会话自始至终与集群所看到的是一个一致的命名空间的注册集合。


  ModeShape有相当多的组件,它们通过一致的方式去使用事件:索引,锁,版本,工作空间的添加/移除,全存储区的设定。


ChangeSet 和 ChangeBus

  要注册一个{敏感词},应用程序必须实现javax.jcr.observation.EventListener接口,然后使用工作区的ObservationManager注册一个实例。标准JCR事件可以描述在节点创建,移动或删除的基本信息,而当属性添加,更改或删除时也是。但仅此而已。


  在内部,ModeShape 采用了更丰富和更细粒度类型的事件。每次提交一个事务时(不管是单个会话保存还是多个保存),所有该次提交所做的变更的描述被捆绑到单个ChangeSet。这些ChangeSet ,在ModeShape中实际上是在集群中承载的,所有的ModeShape 的内部组件被编写来响应它们,通过实现和注册内部ChangeSetListener接口的方式。有趣的是,每次你的应用程序注册一个新的事件{敏感词}的实例,ModeShape 其实注册一个内部ChangeSetListener的实现,这样不过是将每个ChangeSet(及其所描述的变更)转换成一组标准的JCREvent对象。




  每个Repository实例都有一个ChangeBus组件,这个组件负责追踪所有ChangeSet{敏感词}和将所有ChangeSet引向那些{敏感词}。多个内部组件先将ChangeSet对象发送给ChangeBus,然后ChangeBus再将这些ChangeSet对象输送到每个{敏感词}的。快速准确地完成这些动作至关重要。比如,一个{敏感词}不应该干涉或妨碍其他监听。还有,一个{敏感词}应该监听到同一命令里所有发生的事件。


  如果ModeShape被用作集群,ChangeBus需要满足同样的要求,但有一点不一样的:当有一个组件要发送一个ChangeSet,这个ChangeSet会马上通过JGroups被发送到集群的所有成员上,在每个进程上JGroups把这个ChangeSet对象发给ChangeBus,ChangeBus会依次将ChangeSet输送给所有本地{敏感词}。以这种方式,JGroups可以确保所有进程看到ChangeSet对象的同样的命令。


  不用说,ChangeBus非常重要,也相对复杂。2.x版本中起初的设计在3.x中占据篇幅很小,但我们将在4.0版本中展示已将之彻底修补完善。


2.x 和 3.x 的 ChangeBus


  ModeShape 2.x和3.x 使用一个相当简单的设计实现ChangeBus:每个{敏感词}有一个“消费者”的线程在不断运行,从侦听器特定阻塞先进先出队列弹出ChangeSet  对象 ,并调用实际的侦听器。当一个新的ChangeSet将被添加到总线时,ChangeBus增加该ChangeSet 到队列的前面给每一位侦听器。 


  每个侦听器线程 从它自己的阻塞队列消费ChangeSet 对象 


  这样的设计有一些很好的优点:

  1. 该设计相当简单。

  2. 每一个侦听器对ChangeSet中对象的相同顺序可见。

  3. 每个侦听器运行一个独立的线程,所以在大多数情况下每个侦听器都是和所有其他的侦听器完全隔离的(见下文)。 

  4. 由于阻塞式队列,如果一个侦听器是真的很慢并且队列已满,那么ChangeBus尝试添加changeset到队列时将阻塞。但是这还是拖慢了系统(特别是进行更改的会话),带来了一些后端压力,尽管侦听器能跟得上。

同时还有一些缺点:

  1. ChangeSet送达总线的时候,总线不得不依次向所有的{敏感词}队列添加这个ChangeSet,而且在从添加方法返回之前,它一直在做添加这个动作。因此,总线拥有的{敏感词}越多,添加这个动作花费的时间就会越长。

  2. 处于阻塞状态的队列都持有内部锁,在向阻塞队列添加ChangeSet之前必须获取到这把锁,同时消费者进程也参与获取这把锁的竞争。这就会延迟ChangeBus的添加操作。

  3. 要把最新的ChangeSet添加到最后一个{敏感词}队列,只有等到把这个ChangeSet添加到所有其他{敏感词}队列后才可进行。这样就会在ChangeBus接收到ChangeSet和添加这个ChangeSet到最后一个{敏感词}之间产生时间差,添加ChangeSet的{敏感词}越是靠后,这个时间差就会越来越大(这是因为这些{敏感词}位于{敏感词}列表的尾部)。

  4. 如果任意一个处于阻塞状态的队列已经处于满员状态(因为{敏感词}处理ChangeSet s不够快引起的),那么ChangeBus的添加操作就会阻塞。这么做非常好(尤其是在会话状态发生变更的时候),因为它把压力回传给生产者进程,同时也要注意到:在把这个ChangeSet添加到后续队列之前添加操作一直处于阻塞状态。因此即便后续的{敏感词}得以运行,它们也无法意识到新添加的ChangeSet,除非阻塞的那个{敏感词}得以运行。因此添加到ChangeBus的任何一个{敏感词}依赖位于其前的所有其他{敏感词}。

  5. 每个{敏感词}队列都会维护一份ChangeSet对象列表的拷贝,并且对这份拷贝进行了排序。{敏感词}越多,队列就会越多。

  注意:{敏感词}数量越多,对性能的影响就会越大。我们知道3.x版本已经有相当大的时间延迟。而且在4.0的早期预发布版里,我们还在3.x的基础上增加了更多内部{敏感词},并且我们还计划给每个索引提供者增加更多{敏感词}。



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部