QuickFixJ未启用ResetOn标签时序列号维护异常的原因与解决
QuickFIX/J客户端配置文件内容
[default] FileStorePath=storage ConnectionType=initiator SenderCompID= TargetCompID= HeartBtInt=30 ReconnectInterval=5 FileLogPath=logs UseDataDictionary=Y TransportDataDictionary=FIXT11.xml AppDataDictionary=fix/CUSTOM_FIX50SP1.xml #ResetOnDisconnect=Y CheckLatency=N RefreshOnLogon=Y #ResetOnLogon=Y #ResetOnLogout=Y EnableNextExpectedMsgSeqNum=Y PersistMessages=Y TimeZone= StartTime= EndTime= Weekdays= [session] BeginString=FIXT.1.1 DefaultApplVerID=FIX.5.0SP1 SocketConnectHost SocketConnectPort= SocketConnectHost1= SocketConnectPort1= LogonTag=553= LogonTag1=554= [session] BeginString=FIXT.1.1 DefaultApplVerID=FIX.5.0SP1 SocketConnectHost= SocketConnectPort= SocketConnectHost1= SocketConnectPort1= LogonTag=553= LogonTag1=554=
问题现象
- 启用
ResetOnLogon(或ResetOnLogout/ResetOnDisconnect/RefreshOnLogon)时:会话期间断开或重启后重新登录,序列号会重置为1,导致丢失对方发送的部分消息。 - 将所有ResetOn类标签设为
N时,出现三类异常:- 发送方序列号更高:接收方发送重发请求(35=2),发送方补发消息并发送序列重置消息(35=4),但接收方无响应,发送方序列号持续增长,接收方序列号停滞。
- 接收方序列号更高:发送方持续发送注销消息(35=5),而非发起重发请求。
- 每日首次登录:存储文件中接收方序列号为空,登录后发送方序列号增长,但接收方序列号仍为空,无法正常通信。
需求:不依赖任何ResetOn标签实现序列号正常维护,但调整配置后问题仍未解决。
原因分析
- ResetOn类标签启用的问题:这类标签的设计逻辑就是强制重置会话序列号,开启后必然会导致会话中断后序列号回滚,丢失中间未同步的消息,属于标签本身的预期行为。
- 禁用ResetOn后的异常原因:
- 序列号同步机制失效:接收方未正确处理发送方的序列重置消息(35=4),可能是数据字典配置不兼容、自定义FIX规则未定义该消息的处理逻辑,或者
EnableNextExpectedMsgSeqNum配置未生效。 - 发送方重发逻辑异常:接收方序列号更高时发送方未触发重发请求,说明会话的序列号校验逻辑存在问题——要么
PersistMessages虽开启但存储的序列号未被正确读取,要么会话初始化时未加载历史序列号。 - 首次登录序列号为空:
FileStorePath指定的存储目录权限不足,导致无法写入/读取序列号文件;或者会话初始化流程有误,未正确加载或持久化接收方序列号。
- 序列号同步机制失效:接收方未正确处理发送方的序列重置消息(35=4),可能是数据字典配置不兼容、自定义FIX规则未定义该消息的处理逻辑,或者
解决方案
配置层面调整
- 清理重置类标签:移除所有
ResetOnLogon/ResetOnDisconnect/RefreshOnLogon相关配置(包括注释掉的行),让QuickFIX/J使用默认的序列号延续逻辑。 - 校验数据字典:确认
TransportDataDictionary和AppDataDictionary指向的XML文件完整,包含FIXT.1.1和自定义FIX50SP1的所有消息定义,重点检查序列重置(35=4)、重发请求(35=2)的字段和规则。 - 补全会话必填配置:给
SocketConnectHost等空字段赋值,确保会话能正常建立连接;同时确认FileStorePath和FileLogPath目录有读写权限,避免序列号无法持久化。 - 保留核心序列号配置:保持
EnableNextExpectedMsgSeqNum=Y和PersistMessages=Y,这两个配置是序列号持久化和同步的基础。
代码/逻辑层面优化
- 处理序列重置消息:在客户端代码中实现对序列重置消息(35=4)的响应逻辑,主动更新本地的预期接收序列号,确保和发送方同步。
- 初始化序列号校验:会话启动时主动加载存储的历史序列号,若接收方序列号为空,可在首次登录后发送一条测试消息触发对方响应,从而初始化接收方序列号;测试环境下也可手动设置初始序列号,生产环境务必依赖持久化存储。
- 修正重发逻辑:检查发送方的会话逻辑,当检测到接收方序列号高于本地发送序列号时,触发重发请求(35=2)而非注销操作,严格遵循FIX协议的序列号同步流程。
验证步骤
- 重启客户端后,检查
storage目录下的senderseqnum、targetseqnum等序列号文件是否正确更新。 - 模拟会话断开后重连,观察双方序列号是否延续之前的数值,而非重置为1。
- 模拟发送方/接收方序列号不一致的场景,验证重发请求和序列重置消息的交互是否正常。
内容的提问来源于stack exchange,提问作者nux12
相关产品推荐
相关产品推荐

