高级排队引擎

 

上一次修改主题: 2006-08-17

高级排队引擎是 Exchange 2003 邮件处理中的一个关键组件,因为所有邮件都必须通过该引擎来传递,即便发件人和收件人位于同一台 Exchange Server 2003 服务器上也是如此。这使得 Exchange Server 2003 传输组件可以处理每一封邮件。任何电子邮件都必须经过传输子系统的处理。

note注意:
Windows Server 2003 的基础 SMTP 服务使用在 Aqueue.dll 中实现的高级排队引擎来处理收到的邮件。扩展版的 SMTP 服务不使用 Aqueue.dll。Exchange Server 2003 使用在 Phatq.dll 中实现的 Exchange 高级排队引擎来替代该组件。为了加载 Phatq.dll,Exchange Server 2003 在 IIS 元数据库中修改 SMTP 服务的 SmtpAdvQueueDll 属性,使它指向 Exchange 高级排队引擎。Aqueue.dll 和 Phatq.dll 执行类似的功能,但是 Phatq.dll 是唯一能用于 Exchange Server 2003 的版本。

高级排队引擎触发的事件

如下图所示,高级排队引擎充当系统事件、存储事件和传输事件的信息控制器或发送器,它处理到达 SMTP 传输子系统的每一封邮件。

19d38f34-9e8f-430e-8194-c7cfd15dce53

高级排队引擎发送下列事件:

  • **SMTP Transport OnSubmission:**当邮件通过 \分拣目录、SMTP 连接或 Exchange 存储驱动程序到达传输子系统时,发生此事件。为了进行分类、路由和传递,邮件必须传递到高级排队引擎。此操作触发 OnSubmission 事件,也称 OnTransportSubmission。高级排队引擎使用该事件来调用事件接收器(如防病毒扫描),这些接收器将在其他任何传输处理发生之前先检查所有传入邮件。例如,Exchange Transport AntiVirus API 事件接收器就是为 OnSubmission 事件注册的。为该事件注册的另一个接收器是 Exchange Transport XEXCH50 Submission 接收器,该接收器使用 XEXCH50 信封数据准备邮件,这样运行 Exchange Server 2003 的远程服务器便能够对它进行进一步的处理。

    note注意:
    OnSubmission 事件是唯一提供协作数据对象 (CDO) 接口的事件。因此,可以使用 Microsoft Visual Basic 或 Visual Basic Scripting Edition (VBScript) 来对 OnSubmission 事件的事件接收器编程。对于其他所有事件接收器,则必须使用 C/C++ 或 Microsoft Visual C# 来编程。

    基于 CDO 的事件接收器可以为 CDO_OnArrival 事件注册,CDO_OnArrival 事件是 OnSubmission 事件的包装,它为 CDO 格式的邮件提供句柄。使用 CDO_OnArrival 的主要好处是 CD0 邮件对象接口具有许多有用的方法,例如,能够分析 MIME 头和 Request for Comments (RFC) 822 头。有关通过 CDO 接收器扩展 SMTP 服务的详细信息,请参阅 Microsoft 知识库文章 837851,“How to configure an Internet Information Services SMTP virtual server to archive or to remove messages in an Exchange Server 2003 test environment”(英文)。
    基于 CDO 的事件接收器的主要缺点是 CDO 接口增加了开销。基于 VBScript 的事件接收器的执行速度没有使用 C、C++ 或 Visual C# 编写的接收器速度快。还应注意的是,基于 CDO 的事件接收器同步运行,并且处理邮件的时间被限定在 60 秒内。60 秒之后,高级排队引擎便认为脚本未响应,从而停止处理。60 秒的限制是硬编码的,无法更改。此外,CDO 接口无法更改已存储提交的邮件的内容。这是 CDO_OnArrival 事件接收器与其他所有事件接收器共有的一个局限性。此局限性之所以存在是因为 Exchange 将存储提交的邮件转换为临时的 SMTP 版本,以便事件接收器可以对它进行处理,然后在接收器完成处理后,丢弃临时版本。有关详细信息,请参阅 Microsoft 知识库文章 273233,“PRB:CDOEX:Cannot Change MAPI Message Contents in a CDO SMTP Event Sink”(英文)。
    由于 Exchange 丢弃存储提交的邮件的临时副本,因此无法使用事件接收器将放弃声明或其他修改添加到所有出站邮件中,除非强制所有邮件都通过 SMTP 接收。为此,必须在组织中与邮箱服务器分开的桥头服务器上安装事件接收器。运行 Exchange Server 2003 的服务器通过 SMTP 彼此通信,这样传输到桥头服务器的所有邮件都通过 SMTP 到达。

  • **SMTP Transport OnPreCategorize:**就在邮件发送到分类程序前一刻发生此事件。此事件与 OnSubmission 事件类似,不同之处在于它不提供 CDO 版本。默认情况下,不为该事件注册接收器。

  • **SMTP Transport OnCategorize:**必须将邮件分类时,发生此事件。这不是单个事件,而是事件类别。可以为绑定到该类别的接收器触发十种不同类型的事件。绑定到该类别的事件接收器是分类程序接收器,此类接收器解析发件人和收件人,并将分类信息(如每个收件人的主服务器)提供给高级排队引擎。在 Exchange Server 2003 中,为 OnCategorize 事件注册了两个事件接收器:Exchange Categorizer 和 Outlook Mobile Access Push Categorizer(与 Mobile Categorizer 一起在 IIS 元数据库中注册)。Exchange Categorizer 处理电子邮件,以解析收件人信息、展开通讯组列表、检查每个收件人的限制,等等。Mobile Categorizer 为移动设备实现更新通知。

  • **SMTP Transport OnPostCategorize:**在邮件分类后即发生此事件。此时,所有通讯组列表(将本地服务器用作展开服务器)都已展开,并且实际的收件人已在邮件传输信封中列出。默认情况下,不为该事件注册接收器。

    note注意:
    在名为 bifurcation 的进程(在本章后面介绍)中,Exchange Categorizer 可能将邮件分割成多个具有不同内容或信封的独立副本。分类后,将以非关联的方式分别为邮件的每个副本触发 SMTP Transport OnPostCategorize 事件。邮件收件人可能分布在几个不同的邮件副本中。
  • **SMTP Transport OnGetMessageRouter:**要将邮件发送给远程收件人并且必须路由时,发生此事件。这不是单个事件,而是事件类别。对于绑定到此类别的接收器,有多个可以触发的事件。例如,Exchange Server 2003 中确定邮件类型 ID 和下一跃点信息的接收器是 Exchange Router。如果本地邮件连接器的状态发生变化,则高级排队引擎也使用 Exchange 路由器接收器来更新链路状态信息,邮件路由体系结构中对此有说明。

    note注意:
    Windows Server 2003 的基础 SMTP 服务不实现路由器接收器,而是将邮件以点对点的方式发送到最终的收件人目标。
  • **SMTP Transport OnMsgTrackLog:**高级排队引擎处理邮件,以便接收器可以持久跟踪日志文件中有关邮件的信息时,发生此事件。Exchange Server 2003 为该事件实现 MsgTrackLog 接收器,这样便可以将通过高级排队引擎传递的所有邮件的状态信息写入到邮件跟踪日志文件中,后者存储在 \Program Files\Exchsrvr\<服务器名>.log 目录(例如,\Program Files\Exchsrvr\Server01.log)中。

    note注意:
    默认情况下,邮件跟踪是禁用的。
  • **SMTP Transport OnDnsResolveRecord:**域名必须解析为 IP 地址时,发生此事件。Exchange Server 2003 为该事件注册名为 Exchange LoadBalancer 的接收器,该接收器通过多个桥头服务器来平衡路由组连接器的出站邮件传输负载。

  • **SMTP Transport OnMaxMsgSize:**提交的邮件包含的内容超过了当前配置的最大邮件大小时,发生此事件。处理该事件的事件接收器可以重写默认阻止设置。默认情况下,不为该事件注册接收器。

  • **SMTP StoreDriver:**邮件必须保存到磁盘或 Exchange 存储时,发生此事件。这不是单个事件,而是事件类别。对于绑定到此类别的接收器,有多个可以触发的事件。例如,当邮件通过传输子系统传递时,高级排队引擎触发大量的 StoreDriver 事件。本节后面提供了有关 StoreDriver 事件接收器的详细信息。

    note注意:
    SMTP StoreDriver 事件可以由高级排队引擎或协议引擎来触发。

高级排队引擎中的邮件队列

高级排队引擎在内存中维持许多邮件队列。这些内部队列使用一个共享的线程池。可以在 Exchange 系统管理器中查看这些队列。具体地说,在 Exadmin.dll 中实现的 Exchange 队列查看器管理单元通过队列管理接口 (PhatQAdm.dll) 与高级排队引擎通信,从而列出这些队列并执行队列管理功能,如冻结邮件队列中的邮件或撤消冻结。下图显示了高级排队引擎中相对于传输事件而言最重要的邮件队列。

377316fe-ba10-4e7d-8a0c-1dd82708eeca

高级排队引擎使用下列邮件队列:

  • **暂缓提交的邮件:**此队列也叫提交前队列。这是通往高级排队引擎的入口点。将为该队列中的所有邮件触发 OnSubmission 事件。如果此事件成功,邮件将被放入分类前队列中。

  • **等待目录查找的邮件:**此队列也称为分类前队列。这是分类程序的调节队列。此队列包含到达分类程序之前的邮件。分类程序根据 Active Directory 解析发件人信息和收件人信息、展开通讯组列表、检查限制、应用针对每个发件人和每个收件人的限制,等等。SMTP 传输组件中的“Exchange 分类程序”部分有对分类程序的详细介绍。
    邮件分类期间,邮件不处于任何队列中。正在分类的邮件实际是在分类程序中,而未在任何队列中列出。因此,队列查看器可能显示空的分类前队列,而性能监视工具可能在监视过程中为名为 Categorizations 的性能计数器显示正的计数值。默认情况下,高级排队引擎在将邮件保留在分类前队列中之前,最多允许 1,000 个暂缓分类。可以通过如下注册表项来更改该阈值。

    位置

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\SMTPSVC\Queuing

    MaxPendingCat

    类型

    REG_DWORD

    数值数据

    0x3E8

    说明

    指定在高级排队引擎开始将邮件保留在分类前队列中之前,所允许的暂缓分类的最大数目。默认为 1,000 个连接。

  • **等待路由的邮件:**此队列也称为路由前队列。它保留分类后排队等待本地传递或远程传递并已触发分类后事件的所有邮件。高级排队引擎在此时决定哪些邮件必须进入本地传递队列,哪些邮件必须进行路由。对于要发送到远程收件人的所有邮件,高级排队引擎都在 OnGetMessageRouter 事件中调用路由引擎,以确定此队列中每一封邮件的下一跃点,并将邮件移入到其各自的链路队列中。

  • **本地传递:**如果收件人的邮箱驻留在运行 Exchange Server 2003 的本地服务器上,那么邮件分类后将通过路由前队列传递,并进入本地传递队列。邮件分类程序根据指向收件人邮箱存储的收件人 homeMDB 属性设置每个收件人的属性,以指示目标服务器,从而将收件人标记为本地。对于本地收件人,将跳过 OnGetMessageRouter 事件,并且高级排队引擎在触发 StoreDriver 事件之前,将邮件移入本地传递队列中。StoreDriver 事件通知 Exchange 存储驱动程序,邮件必须传输到 Microsoft Exchange Information Store 服务。

  • **动态传递:**这些队列是名称与远程域或链路上的下一跃点地址匹配的域队列。队列名标识了目标。
    一种特殊的情况是通过 Exchange MTA 进行的邮件传输(通常称为网关传递),因为 MTA 还负责所有基于 MAPI 的非 Exchange 邮件系统连接器,X.400 传输体系结构网关邮件连接器体系结构对此有详细说明。SMTP 传输子系统使用 Exchange 存储驱动程序并通过 Exchange 存储将邮件移入或移出 MTA。但是,在路由引擎返回有关邮件必须通过 SMTP 传输还是必须通过 MTA 传输的信息之前,高级排队引擎不知道这一信息。如果收件人的下一跃点是非 SMTP 连接器(如果路由组连接器实例没有 Exchange 5.5 桥头,则路由组连接器被认为是 SMTP 连接器),邮件将被发送到 Exchange MTA 传递队列,然后再传递到本地传递队列。然后再由 Exchange 存储将邮件从本地传递队列发送到 Exchange 存储。分类程序在邮件传输信封中设置的收件人属性,用来区分哪些收件人的邮件必须传递到本地邮箱,哪些收件人的邮件必须传递到 Exchange MTA。

  • **系统:**这些队列包含具有特定参数的邮件。除传递队列以外,下表还列出了高级排队引擎维持的系统队列。

    高级排队引擎中的系统队列

    队列 说明

    目标不可达的邮件

    此队列包含无法到达其最终目标服务器的邮件。例如,Exchange 无法确定到达最终目标的路由路径或连接器,或者所有可用的路由路径或连接器都标记为 down。

    正在排队等待稍后传递的邮件

    此队列包含正在排队等待稍后传递的邮件。此队列可能包含早期版本的 Microsoft Outlook(如 Microsoft Outlook 2000)发送的邮件。较新版本的 Outlook 在 Exchange 存储中存储这些类型的邮件。在预定的传递时间到来之前,邮件保留在“正在排队等待稍后传递的邮件”队列中。

    note注意:
    此队列所包含的某些邮件还可能发送到最近已移至另一个邮箱存储或 Exchange 服务器、正等待目录复制更新其位置的邮箱。

    暂缓提交的 DSN 邮件

    此队列包含正等待 Exchange 生成的传递状态通知。例如,如果邮件保留在邮件队列中的时间过长,高级排队引擎会生成一条传递状态通知,以通知发件人邮件已传递。未送达报告 (NDR) 也是传递状态通知。有关传递状态通知的详细信息,请参阅下列 Microsoft 知识库文章:

    重试已失败邮件

    此队列包含队列提交失败的邮件。邮件可能由于几个原因而导致队列提交失败,并且失败可能发生在执行其他任何处理之前。如果邮件已损坏或者系统资源不足,邮件便会出现在此队列中。

    限制邮件队列中的邮件数

    邮件队列中的每一封邮件都至少需要 4 KB 的内存。因此,如果队列非常大,可能会出现内存不足的情况。为避免这种情形,可以使用下列注册表参数来限制给定时间存储在队列中的邮件数。

    Caution警告:
    错误地使用注册表编辑器可能导致严重的问题,甚至可能需要重新安装操作系统。Microsoft 无法保证错误使用注册表编辑器所导致的问题可以得到解决。请自行承担使用注册表编辑器的风险。

    位置

    HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Mailmsg

    MaxMessageObjects

    类型

    REG_DWORD

    数值数据

    0x000186a0

    说明

    如果不指定值,则默认为 0x000186a0 (100,000) 封邮件。指定较低的值将减少最多可以驻留在高级排队引擎中的邮件数,从而减少 SMTP 占用的最大内存量。到达此限制后,与服务器建立的每个 SMTP 连接将返回内存不足的错误消息。例如,如果该值减小到 10,000 封邮件,则当队列中的邮件数达到 10,000 后,SMTP 将不再接受入站邮件。