拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dynamics 365集成排查指南:AIF、业务事件日志与消息监控全解析

Dynamics 365集成排查指南:AIF、业务事件日志与消息监控全解析

1. 方案底板:AIF、BEL 与 Message Monitoring 在集成链路里的分工

先说结论:在 Dynamics 365 Finance and Operations 和 AX 2012 这类 ERP 环境里,AIF(Application Integration Framework)、业务事件日志(Business Event Logging)和消息监控(Message Monitoring)这三样东西经常被放在一起讨论,但很多人一开始都会被名字绕晕。AIF 管的是消息管道,BEL 管的是事件记录,而 Message Monitoring 则是你盯着这两层运行时状态的窗口。它们不是同一个东西,更不是可以互相替代的东西,而是一条链路上的三个环节。

拿一次典型的对外集成来举例:业务用户在系统里过了一张销售发票,系统根据你配置的规则发布一个“发票已过账”的业务事件;这个事件如果被订阅了,就会通过集成框架转成一条出站消息,塞进 AIF 的队列等待发送;第三方 ERP 收到之后返回确认,这条消息才会在监控界面里被标记成已完成。如果这一过程中任何一环出了问题——事件没发布、消息没进队、第三方接口超时——你就需要消息监控界面来定位到底是哪一段断了。这就是这篇文章想讲清楚的核心场景。

我最早开始用这套东西,是在做 AX 2012 和外部仓库系统对接的项目上。当时业务方报“单据没过去”,我第一反应是去看业务事件日志,结果发现事件明明记录了;再一查 AIF 消息,发现出站消息的状态卡在了 Ready,队列里堆了一排。如果只看事件日志,永远发现不了问题出在传输层。后来总结出一个经验:遇到集成问题,先看事件日志确认业务是否触发,再看消息监控确认传输是否完成,两边的数据一对,责任范围就切清楚了。适合来看这篇文章的,主要是 ERP 集成开发和运维人员,也包括刚接手 Dynamics 集成模块、需要搞清楚整套消息机制的新人。下面我把这套方案从设计到实操一步步拆开讲。

2. 配置与监控实操:从业务事件订阅到消息查询的全流程

2.1 先从业务事件日志入手,确认业务侧真的发生了

业务事件日志是整条链路的最前端。很多集成排查都是从“业务没触发”开始的,而 BEL 就是用来告诉业务人员和技术人员“系统内部确实发生了某件业务动作”的那份凭证。在 D365 的界面上,事件日志可以在组织管理模块下的业务事件相关菜单里查看,每一行记录都对应着一个业务事件实例,字段通常包括事件 ID、业务实体、发生时间、相关的公司帐套,以及对事件上下文有用的数据载荷。

配置业务事件订阅的时候,有一个原则我特别想强调:先在测试环境跑通一个最小业务动作,确认事件日志里能出现记录,再做下一步消息集成。不要一上来就把几十个业务事件全部订阅,因为这样一旦集成出问题,你很难判断是哪个事件配置错了,还是消息管道有问题。我见过一个项目把所有标准事件全勾上,结果生产环境日志表里每天多出上百万条记录,后台批处理直接被拖垮。后来清理配置、只保留实际在用的十几个事件,性能才恢复正常。

还有一个容易被忽略的点:BEL 的事件日志本身不一定等于 AIF 消息。事件日志只是“记录发生了什么”,它是否被转成消息、是否成功发送,取决于你的事件订阅有没有绑定可用的 AIF 通道或终结点。这也是为什么单看业务事件日志远远不够,必须切换到消息监控这一层来看传输状态。

2.2 理解 AIF 消息的生命周期,才知道监控里那些状态到底什么意思

AIF 处理消息的过程有点像医院的分诊台。患者(业务事件)到了之后先登记,领取一个编号(消息 ID),然后根据病情被分到不同的科室(管道和队列),科室处理完之后,病历归档(消息日志)。如果中间环节发现患者病情不对,就会打回分诊台重新分配。AIF 出站消息的默认流转路径大致是:业务事件产生消息记录 → 消息进入出站队列 → 系统尝试发送到目标系统 → 收到响应后消息状态变为已发送或已完成。

在消息监控界面里,你会看到每条消息的当前状态,常见的有 Queueing、Ready、Processing、Sent、Failed、Canceled 等。翻译成人话就是:排队中、可以发送了、发送中、已发送但还没确认完成、失败被挂起、被人为取消。这里最容易让新手困惑的是 Ready 和 Processing 之间的切换。Ready 表示消息已经进入队列,等待处理器拾取;一旦处理器开始发送,状态会变成 Processing;如果发送成功并收到目标系统确认,状态就会走到 Sent 或 Completed。如果处理器在发送过程中抛出异常,消息状态会变成 Failed,同时系统会记录失败次数和错误详情。

理解这个状态机最大的价值在于:你能根据状态判断故障的大致位置。比如消息一直停在 Ready,说明处理器进程可能没跑,或者队列没有被释放;消息状态是 Failed,说明已经进入了重试逻辑,重点要看异常文本;消息显示 Sent,但第三方说没收到,那就不是 AIF 的问题,而是第三方接收端或接口网络的问题。用这套思路去排查,比盲目翻日志高效得多。

2.3 实操查询:找到一条出站消息并解读它的状态

我以自己常用的排查路径为例。手动触发一个业务事件之后,打开 AIF 消息监控页面,使用消息 ID 或业务参考字段做筛选。如果不知道消息 ID,可以根据时间范围、公司、消息方向(出站/入站)来过滤。找到目标消息之后,主要看三个地方:第一是消息状态,第二是队列名称,第三是日志标签页里的异常文本。

有一次我排查一个“客户主数据无法同步”的问题,消息监控里那条客户消息的状态是 Failed,日志标签页里写着“The server returned an error 500 on request”。当时立刻判断不是 AIF 本身的问题,而是目标系统的接口挂掉了。后来联系目标系统负责人修复接口,消息通过手动重置之后重新发送就成功了。另一个案例是消息状态显示 Ready 但一直不动,日志页是空的,后来查到是后台 AIF 网关服务对应的批处理作业停止了,把批处理作业重新启动之后,队列里的几十条消息很快全部发出去。这类问题的解法并不复杂,难的是先通过状态和日志确认位置。

查询界面概览方面,消息监控一般会提供“历史记录”“当前活动”“队列信息”等不同视图。历史记录大多是对已完成消息的留档,当前活动主要反映还在队列中或正在处理中的消息,队列信息则直接列出各队列的长度和处理器状态。我习惯先打开队列信息,看哪个队列积压严重,再从那个队列里挑一条代表消息去查它的完整生命周期。

3. 失败消息处理与状态机解码:别再一路点击“重置”了

3.1 重置消息的正确姿势和顺序

很多运维人员遇到失败消息,第一反应就是选中消息,点击重置,然后希望它能自动恢复。这操作本身没错,但前提是你已经确认了失败原因并且修复了根因。否则重置之后消息大概率会再次失败,而且每失败一次,都会产生新的异常日志和重试记录。整个系统里如果同时有大量消息处于反复失败-重置的状态,消息日志表会迅速膨胀,直接影响后台作业性能。

正确的处理顺序应该是:先打开失败消息的日志,确认异常类型是网络超时、权限拒绝、数据格式校验失败还是目标系统返回的业务错误;针对根因修正配置或通知目标系统处理;最后再重置消息。这里有一个重要的细节:重置的方向要正确。出站消息的重置通常是重新发送,入站消息的重置则一般是将消息放回到入站队列,让系统重新处理。不要看到“重置”就点,方向错了会导致数据重复入账。

如果一条消息反复失败,建议先去检查是否为目标系统接口的幂等性问题。比如外部系统已经成功接收了消息,但因为响应超时没来得及给 AIF 返回确认,导致 AIF 判定发送失败。这种情况下盲目重置会重复调用目标系统接口,产生重复单据。稳妥的做法是先和外部系统确认当前数据是否存在,再决定重置还是放弃。

3.2 分批处理和批处理组的关系:消息监控背后的执行引擎

AIF 消息不会凭空被发送,必须由一个在后台运行的处理器来执行。在 D365 和 AX 2012 中,这个处理器通常以批处理作业的形式存在。你可以把批处理作业理解为 AIF 的“邮递员”,邮递员什么时候上班、哪些消息排在今天负责发送,由批处理组和调度决定。如果邮递员没上班,消息监控里就会出现大量 Ready 状态的消息,但它们并不需要人工干预,而是把邮递员的班次恢复即可。

在配置批处理组的时候,我一般会把 AIF 消息处理相关作业单独放到一个批处理组里,不和其他重负载作业混在一起。这样在出现消息积压时可以单独重启该组,不影响其他后台流程。监控方面,除了看 AIF 队列长度,还要顺手看这个批处理组的上次运行时间,如果很久没跑,八成是作业停掉了或者服务器节点有问题。

这里还要提一下“管道”的概念。AIF 里的管道决定了消息使用哪种传输机制:文件、HTTP、MSMQ、BizTalk 等。不同管道的消息发送行为不一样,特别是超时和重试机制差别很大。比如文件管道只要写入文件就算完成,而 HTTP 管道必须等待目标系统返回 HTTP 响应才算发送成功。所以同样是 Failed 状态,基于文件管道的消息多半是写入共享路径失败,基于 HTTP 管道的消息则需要关注接口响应码。在监控里看到消息所属管道,能帮你快速缩小排查范围。

3.3 手动将消息状态从 Failed 恢复到 Completed 的后果

有几次为了赶数据,我直接通过后端更新消息状态,把失败的出站消息改成 Completed,当时看着问题“消失”了,事后却发现目标系统其实未收到数据,还得重新做一遍补单。这类操作非常不建议。AIF 消息状态不是一个单纯的标识位,它还关联着消息日志、队列记录、重试次数和后续的业务动作。强行把状态改成 Completed,相当于告诉系统“这条消息处理成功了”,但真实业务并没有完成,后续的审计和对账会产生混乱。

正确的办法是:如果真的不想再重发某条消息,在 AIF 里应该使用取消或拒绝等明确的操作,并且要确认业务侧该做补偿的补偿、该做删除的删除。千万不要因为嫌日志难看就在后台直接改状态。这个坑我踩过,也亲眼见过同行踩过,这里多说一句:生产环境里,任何“绕过界面直接改库”的操作都应该在变更记录里留痕,否则出了问题很难追溯责任。

4. 常见问题与排查技巧实录:从现象到根因的几条经验

4.1 事件日志里有记录,但消息监控里完全查不到消息

这是一个非常典型的现象。事件日志显示了某条业务记录,但消息监控里没有对应的出站消息,很多人会误认为是 AIF 没配置好。我遇到这个问题的次数不少,根因通常不在 AIF 消息管道,而是在事件订阅到消息生成的中间逻辑上。

可能的原因有以下几类:事件订阅没有关联有效的 AIF 集成通道,事件产生了但没有被转发成消息;业务事件发生的数据类型或公司条件不满足消息生成的过滤规则;消息生成过程中出现了异常,异常被记录到系统的基础日志里,但消息监控看不到;还有一种情况是消息确实生成了,但查询条件被日期时间范围限制住了,默认视图只显示最近几天。排查时不要只看事件日志,还要去查系统的基础任务记录或操作日志,看看有没有报错。

我给出的建议是:把“事件生成消息”的过程想象成一道流水线,事件日志负责登记零件,消息队列负责运输成品。如果登记了但没有成品,一定是流水线中间的某个执行步骤停了或者卡住了。优先去看后台作业的执行历史,特别是和事件转发相关的批处理任务,绝大多数情况下会得到明确的错误信息。

4.2 消息状态一直停在 Ready,队列越积越长

如果消息监控里大量消息停留在 Ready 状态,而且队列不断增长,这通常不是消息本身的问题,而是“发送引擎”没在工作。和人工处理不同,AIF 的处理器是按既定的批处理周期运行的,如果批处理作业意外停止,或者被挂起的消息阻塞了队列头,后面的消息就会一直排队。

我曾经处理过一个案例:某条消息因为目标系统返回了无法识别的数据格式,处理器在反复重试该消息时占用了队列锁,导致后面的所有消息都停留在 Ready。通过消息监控看到队列头有一条 Processing 状态的消息,但它已经卡了两个小时。解决方法是手动重置头部消息,让它进入 Failed 状态,队列后面的消息才开始正常发送。那次之后,我每次检查积压队列都会先关注队列头的那一条,而不是把全部消息重置一遍。

平时也可以设置一个预警作业,定时检查 Ready 状态消息的数量,超过阈值的时候发系统通知。不需要做得很复杂,统计队列长度并和上周同时间段的平均值做对比,就能在业务人员发现之前抓住问题。

4.3 消息出现重复发送,目标系统收到多份数据

排查询问题时,常常遇到“目标系统重复数据”的投诉。AIF 里重复发送的原因一般有两种:第一种是发送超时但目标系统已经处理成功,AIF 没有收到确认,重试时重复提交;第二种是人工重置了一条已完成状态但其实响应信息没有被正确解析的消息。这类问题的关键不在 AIF 本身,而在于目标系统接口是否实现了幂等。

作为集成方案的设计者,应该主动检查目标系统接口文档里是否有幂等键字段,如果没有,建议在数据载荷里带上业务参考号,并在目标系统里做唯一性校验。AIF 消息本身一般有消息 ID,可以在转发时把消息 ID 作为幂等键传给目标系统。如果目标系统已经存了同一条消息 ID,就直接返回成功,不重复创建业务数据。

如果问题已经发生,最优先的工作是确认哪条消息是合法的、哪些是重复的,然后和业务方确认是否需要删除重复数据。删除前保留好消息监控的日志截图,方便审计说明。对于反复出现的重复发送,建议开启 AIF 消息日志的详细记录,留出异常发生前后的完整证据链。

4.4 消息日志表膨胀严重,后台性能明显下降

AIF 消息监控运行时间长了,消息日志表会越积越大,这在生产环境几乎是必然的。如果日志清理作业没有配置好,大表会影响写入性能,进而拖慢消息处理。不要等到业务反馈系统变慢再去处理,日志表的膨胀速度是可以通过 SQL 查询预估的。我之前做过一个统计:每天大约增加 5 万条消息日志,如果不清理,三个月就能到 450 万条以上,这时候任何按消息 ID 的查询都会明显变慢。

我的经验是配置定期清理作业,将超过保留期的历史消息日志归档或删除。保留期根据项目审计要求来定,我一般建议至少保留 90 天,但不要超过一年,除非有法规或客户合同的强制要求。清理作业需要关注批处理执行时长,如果表数据量特别大,清理一次要跑很久,那就把它拆成按公司或按日期范围分批执行,避免对正常业务造成压力。另外,在清理之前,一定要确认消息监控的历史记录不是你们财务对账的唯一依据,必要的时候先做备份。

4.5 排查思路速查表

现象检查重点常见根因初步处理方式
事件日志有记录,消息监控没有事件订阅与 AIF 通道关联、后台作业执行历史事件未关联通道、转发作业停止检查订阅配置和批处理作业
消息状态持续 Ready队列头状态、批处理作业运行时间处理器未运行、队列头消息阻塞重启批处理,重置阻塞消息
消息状态 Failed日志异常文本、目标系统响应码接口超时、数据格式校验失败修复根因后重置消息
目标系统重复数据消息 ID、目标系统幂等校验超时重发、人工误重置确认重复范围、补幂等键
日志多、查询慢表容量、清理作业状态日志清理未启用配置定期清理,按批次执行

5. 消息监控之外的长期运维:日志规范、权限与监控前置设计

5.1 给消息取一个方便追踪的业务参考号

AIF 的消息监控看起来很强大,但如果每条消息没有明确的业务参考号,查询时只能靠时间范围和消息 ID 来猜。消息 ID 是一串系统生成的编号,业务人员根本看不懂。每次要在几十条类似消息里找特定单据对应的那条,效率非常低。

我的建议是在设计集成方案时,将业务系统的单据编号映射到 AIF 消息的业务参考字段里。比如销售订单同步,就把订单号写入消息描述或业务引用字段。这样在消息监控页面里一眼就能看出哪些订单同步成功、哪些失败,不需要打开每条消息看载荷。这个习惯越早养成越好,等上了生产再补会非常痛苦。

消息监控里虽然可以通过载荷内容筛选,但界面上直接支持字段查询的效率远高于在 XML 里硬翻。给每类消息约定一个前缀或编号规则,既是给自己排查留后路,也是给将来接手的人留线索。

5.2 消息监控页面的权限控制

AIF 消息监控里能看到真实业务数据,这也意味着它不是所有人都应该能打开的页面。有的项目里,业务顾问和外部开发人员都能访问消息监控,结果误操作重置了消息,引发重复发送。权限控制要从一开始就做好,在 D365 的安全配置里,只给集成运维团队开放消息监控和重置权限,给业务人员的只读权限,甚至只开放事件日志相关页面。

严格来说,“重置”和“取消”这类破坏性操作应该控制在最小必要范围,并且建议通过安全角色区分。如果内部团队人员流动大,最好在权限配置文档里写明哪些角色能查看消息、哪些能操作消息、哪些只能看日志。每个季度过一遍权限清单,比出了问题再去追责要省心得多。

我还遇到过一种情况:运维人员重置消息时没有记录操作原因,事后查不到是哪个人动了哪条消息。如果环境允许,建议开启操作审计功能,或者建立一个人工登记流程。这样在集成故障复盘时能清楚地知道每一步操作的时间和操作人,避免责任不清。

5.3 把消息监控设计成前置巡检项,而不是事后补救

消息监控的价值不只是出问题的时候翻一翻,它完全可以做成日常巡检的一部分。我推荐的做法是每周固定时间检查三个核心指标:失败消息数量、队列积压数量和消息平均发送耗时。失败消息数量如果持续增长,说明有系统性故障;队列积压说明处理器运行不稳定;发送耗时突然变长,则要考虑目标系统性能或网络链路。

把这几个指标记录下来,坚持几周之后,你会对自己这套 AIF 集成体系的“正常水位”非常清楚。之后任何偏离,你都能比业务方更早发现。真正做得好的人,往往不是在故障现场翻日志翻得最熟练的人,而是那些在故障发生之前就把监控规则定清楚的人。AIF 给了你消息监控这双眼睛,怎么用好它,取决于你平时养成了什么样的巡检习惯。一套稳定的集成链路,从来不是靠应急救火救出来的,而是靠日常对消息状态的持续观察一点点稳下来的。

返回列表