1. 一个程序应该建立几个收发的传输端点?
一个传输端点可以用来传输一类消息,每个传输端点关联的传输通道数则要根据发送端和接收端的分区个数来确定,一般为两者的乘积。两个不同名称的传输端点也可以关联到同一传输通道的不同端。
2. 只启动发送端或接收端组件,是否会收到对方的超时事件?
对于发送端组件,有消息发出后,接收端组件还未启动,发送端会收到超时事件。
对于接收端组件,当发送端启动之后故障退出,接收端才会收到超时事件。
3. 如果应用长时间未收到消息会收到报警信息吗?
目前FINBUS™未提供该事件告警。
4. 收发消息是否支持超时机制?
发送消息时,应用可以通过指定SendMsg和GetMsg接口中的超时时间。
当该值为-1时,SendMsg和GetMsg操作不能完成时将阻塞应用线程;
当该值为0时,SendMsg和GetMsg操作不能完成时立刻返回;
当该值大于0时,SendMsg和GetMsg操作不能完成时等待指定的时间。
当某个传输通道被配置了发送端故障隔离功能,使用该传输通道发送消息不会阻塞。
5. 队列模式和回调模式下消息的生命周期有何不同?
回调模式下消息只能在回调函数内被使用,如果应用要在回调函数之外引用该消息,应用需要在回调函数中将消息的内容拷贝。
队列模式下应用调用ReleaseMsg接口将消息释放之后,便不能再引用该消息。FINBUS™对消息释放的顺序没有要求,但若应用内存泄露没有释放消息,FINBUS™可能会死锁,即应用不会再获取到新的消息。
6. 将会话Close()之后,应用是否就还会收到新的消息?
FINBUS™会话的Close接口可以在回调函数中使用,因此是异步的。会话被Close后,FINBUS™会尽快停止消息递交和发送。只有在调用会话的Join接口等待会话完全关闭之后,才能保证应用不会再收到或发出任何新的消息。若应用在FINBUS™回调函数中调用会话的Close接口,也可以达到同步停止消息递交的效果。
7. 区分四种启动模式
(1)初始(Normal)启动
所有组件第一次启动均使用Normal start,该启动模式下发送消息的序列号从1开始,接收的消息序号也从1开始。假如一个组件运行了一段时间故障退出,错误使用了normal start启动,它会发现接收的消息序号不是从1开始,而且对应的transport是要求历史消息的,该组件将会向发送方要求消息重传。因为消息重传是以transport为单位顺次获取的,因此若一个本不应normal start的组件采用了normal start,组件通过重传获得历史消息,那么这些历史消息的全局顺序与重启前处理的消息的顺序很可能就不一致了,应用处理了这些消息,把输出发送到下游,发送的消息很大可能与已经发出的不一致,下游组件接收到这些消息后,会先把重复的消息扔掉,然后把为处理的序号的消息当作新消息来处理,那么最后就会导致程序处理了错误的数据。因此,目前除了第一次启动使用normal start以外,其他场合要非常慎重地使用normal start。
(2)延迟加入(late join)启动
只对真正的多成员Cluster有效,前置条件是存在一个正常工作的leader,latejoin成员会顺次把本地存储的数据,leader存储的数据以及本地实时接收的数据重演,直至与leader同步。Latejoin启动相对来说没有太大的风险,模式用错了或者数据错误了会latejoin失败,不会造成系统的错误运行。一个cluster内每次只能启动一个组件进行latejoin,不然多起的组件会latejoin失败。
(3) 整层恢复(Recovery)启动
singleton或者真正的cluster均有效,前提是整个cluster无成员存活,找到消息最多的成员,然后recovery启动,先从本地的recorder获取消息进行重演,然后转入实时数据流,recovery成功。每个cluster同时只能有一个组件recovery。
若一个组件一开始就使用recovery启动(本应使用normal start),理论上是没问题的,因为第一次启动本地也没有数据,不存在重演数据错误的问题。
若一个组件本应continue启动,却使用了recovery,可能会出错,因为某些情况下不需要重新恢复历史消息,会造成下游一直过滤掉历史消息,导致长时间收不到新消息,因此,手工选择启动模式时还是要慎重。
(4)接续(continue)启动
只适用于singleton组件,continue启动时,该组件的发送方向会从当前消息开始发送,若一个本应continue启动的组件使用了normal start,下游接收方向的组件会把前面已经处理过的消息序号的消息都扔掉,例如下游已经处理了100个消息,那么刚启动的组件发送的前100个消息都会被扔掉,而这100个消息对于该应用来说应该是新消息不应该扔掉的。
8. Recorder的启动和恢复
Recorder启动有两种模式,recovery模式和普通模式:
如果shm不存在,recorderdata目录也没有数据,使用normal模式启动,这是最正常的启动模式,一切从0开始;如果使用recovery模式启动,直接恢复启动成功,两种模式都可以。
如果shm存在,recorderdata目录数据也存在,使用normal模式启动和recovery启动是一样的,recorder将会自动从recorderdata和shm恢复启动。
如果shm存在,recorderdata目录不存在,normal启动会返回错误,要求手工删除共享内存;recovery启动,recorder会直接attach shm,而且能够启动成功,shm中若还有数据,那么旧的数据就会混杂在新数据中,导致数据错误(考虑后续对这种情况直接报错退出,或者用其他手段提示风险)。
如果shm不存在,recorderdata目录存在,normal启动,先备份data数据,然后清理data数据,再启动;recovery启动则是从文件恢复数据后继续启动。
总结来说,初次启动一律用normal启动recorder;若组件发生故障(非服务器或操作系统故障),在没有去做数据删除前,使用normal启动或者recovery启动效果是一样的;若发生服务器或操作系统故障,我们一般认为共享内存就不可用了,此时recorderdata有数据,那么此时的数据有可能是不完整的,可是这部分数据是正确的,因此,我们的处理可以是直接normal启动recorder,这样相当于是不要recorderdata的数据了;我们也可以使用recovery启动recorder,这样启动恢复的recorder会把recorderdata部分的数据恢复,两种情况的差异是恢复模式下启动后数据更多,相同点是都可能不完整,没有本质的差别,都不影响后续应用的启动动作。
另外需要注意的是,所以当我们真正需要用recovery模式启动recorder时(没有shm但有recorderdata时),要手动先把recorder启动起来。
recorder故障,实例会继续运行一段时间,直至共享内存写满,报msg queue full错误事件导致实例退出。要恢复组件,可以先进行实例的recorder恢复操作,等原主实例共享内存消息写入磁盘后,再进行后续操作。
如果配置了finbusHome配置项,并且配置Session可以持久化(enableInRecord = true or enableOutRecord = true),则在组件启动时,Session解析消息总线参数时, recorder会设置启动模式(Latejoin/ClusterRecovery下使用-R模式,其他情况使用普通模式)。在启动Session时自动启动recorder组件。
9. 高可用和非高可用、singleton会话的区别?
我们可以将会话分为高可用、非高可用和singleton,可以通过配置文件isHa和isSingleton来配置。
高可用会话会将会将同分区不同实例组合一起成为cluster,并会选举出主备实例,当主备实例出现故障的时候,cluster会自动接管并舍弃备实例或者重新选出主实例。
非高可用会话只有消息收发功能,而且成员之间并不会组成cluster,也并不会有主备实例之间的消息同步,非高可用的会话一定是一个singleton会话。
singleton是一种特殊的高可用会话,成为singleton的会话主备之间消息不做同步。有两种方式可以成为singleton会话,一是通过isSingleton属性配置为true;二是当cluster内只有一个成员的时候自动成为singleton,此时只有一个成员也无法做主备消息同步。
当一个会话是高可用的,会话下所有的Endpoint也是高可用的。