通过 Enterprise Library 5(EntLib)日志记录应用程序块和 MSMQ 分布式服务实现通用和分布式日志记录






4.75/5 (10投票s)
关于如何通过 Logging Application Block 实现可靠且高性能的日志记录,以及通过 MSMQ Distributor Service 实现分布式日志记录。
引言
在设计任何新应用程序时,有一个重要的关注点——构建一个可靠且高性能的日志记录引擎。经过大量的调查和研究,我们发现推荐的框架是 Enterprise Library 5.0 配合 MSMQ distributor service。
在本文中,我们将介绍两种方法;一种是通过 **Logging Application Block** 进行通用日志记录,然后通过 **MSMQ Distributor Service** 进行日志记录。
1. 设置
在继续之前,我们需要在我们的 PC 上安装一些东西
- Enterprise Library v5.0
- 消息队列
Enterprise Library:Enterprise Library 包含一系列应用程序块和核心基础设施。所有这些都是可重用的软件组件,旨在协助开发人员应对常见的企业开发挑战。Enterprise Library 还提供了许多高度可配置的功能,使得管理应用程序中许多地方出现的重复性任务更加容易。这些任务包括日志记录、验证、缓存、异常管理等。在这里,我们只关注 **Logging Application Block**。
下载并安装 Enterprise Library v5.0。请注意,我们在此过程中安装的不仅仅是日志库。请保持耐心。
Message Queue:Message Queuing(也称为 **MSMQ**)是一个消息传递基础设施和环境,用于运行分布式、松耦合的消息应用程序。源计算机上运行的消息队列应用程序将消息发送到队列,消息在那里被临时存储,目标计算机上运行的应用程序从队列中检索消息。此类应用程序可以跨异构网络以及与可能暂时离线的计算机进行通信。
消息队列在 Windows 安装过程中默认不安装。 这里是安装 MSMQ 的步骤。
2. 概念
Logging Application Block
Enterprise Library Logging Application Block 简化了通用日志记录功能的实现。我们可以使用 Logging Application Block 将信息写入各种位置
- 事件日志
- 电子邮件消息
- 数据库
- 消息队列
- 文本文件
- Windows® Management Instrumentation (WMI) 事件
- 通过应用程序块扩展点自定义位置
虽然创建和写入日志条目的过程相对简单,但可用的选项数量(例如许多日志记录目标和过滤条目的能力)意味着该块的底层结构以及使用它的可用选项可能看起来很复杂。下面的示意图显示了块中主要对象类型如何协同工作,以在创建和写入日志条目时提供灵活性。
七种主要对象类型是
- Logger:
Logger
是一个static
类,提供典型的日志写入 API。有许多重载 API,可以根据日志路由到相应的日志记录目标。 - Log Entry:Log Entry 表示一个日志消息。它包含所有日志消息所需的通用属性,如优先级、严重性和类别等。
- Log Writer:Log Writer 是创建日志条目并将其写入我们选择的日志记录目标的主要入口点。它创建一个日志条目实例,包含要记录的信息,并与其他对象交互,这些对象会过滤日志条目、将其分配给一个或多个类别、格式化它,然后将其分派到适当的目标。
- Log Filters:Log Filters 可以根据多项功能阻止或允许日志条目。每个日志条目都被分配到一个或多个类别(默认是 General 类别),并且类别日志过滤器可以使用这些类别来传递或阻止日志条目。此外,两个特殊的日志过滤器可以阻止所有日志记录,或阻止优先级低于指定值的日志条目。我们在块的配置中定义类别、优先级和日志过滤器的设置。
- Trace Sources:Trace Sources 实际上是一组存储桶,块将所有未被日志过滤器阻止的日志条目放入其中。我们使用这些存储桶来定义日志条目的分派位置——我们可以将它们视为将实际分派到目标目的地的日志条目的来源。
有两种基本的 Trace Sources 类型 - Category Sources:我们将在块的配置中定义的每个类别都有一个 trace source。
- Special Sources:有三个内置的 trace sources:一个接收所有日志条目,一个在处理或分派日志条目时发生错误时接收日志条目,还有一个接收所有未匹配任何配置类别的日志条目。
- Trace Listeners:Trace Listeners 代表我们日志条目的目标,我们为每种要将日志条目发送到的目标类型(例如 Windows® 事件日志、磁盘文件和电子邮件消息)配置一个。Trace Listeners 监听进入 trace source 存储桶的日志条目,按需格式化每个日志条目,并将其分派到为该 trace source 配置的目标。我们的配置将每个 trace source(我们定义的每个类别源加上三个特殊源)映射到一个或多个 trace listeners。需要注意的是,这允许我们将每个日志条目分派到零个、一个或多个目标(例如,将其作为电子邮件发送,并写入 Windows 事件日志)。
- Log Formatters:我们添加到配置中的每个 trace listener 都可以使用日志格式化器将日志条目中的数据从一系列属性转换为适合发送到日志目标的格式。该块包含一个文本格式化器,我们可以用它配置将日志条目分派到磁盘文件、电子邮件或 Windows 事件日志等目标的 trace listeners;以及一个二进制格式化器,它将日志条目数据序列化为适合传输到 Windows Message Queuing (MSMQ) 等目标的格式。文本格式化器是可配置的,因此我们可以修改文本消息的格式和内容,包括使用占位符来表示日志条目属性的值。
日志记录过程序列
尽管从对象描述中我们现在应该清楚日志记录过程了,但以下步骤将详细描述该过程,以帮助我们理解它如何与它使用的对象集相关联。
- 我们的应用程序通过使用
static
类Logger
或LogWriter
类来自动创建日志条目,或者通过直接创建LogEntry
类的实例并用要记录的信息填充它,来提交要记录的信息给 Logging Application Block。日志条目可以定义一组映射到配置中定义的类别的类别。此映射控制块应用于日志条目的进程(它使用的过滤器和源)。 - Log writer 将日志条目通过我们在配置中定义的日志过滤器。这些过滤器可以根据其优先级、类别名称阻止日志条目,或者在未启用日志记录时阻止。
- 如果日志过滤器未阻止日志条目,log writer 将检索适当的 trace sources。我们可以使用的 trace sources 包括一组我们创建和配置的类别源,以及三个我们可以用来确保块记录所有日志条目的特殊源(例如,如果日志系统出现错误,或者如果日志条目未匹配任何配置的类别)。
- 我们可以为每个 trace source 配置一个或多个 trace listeners。换句话说,我们可以为消息可能包含的每个类别以及可能处理消息的三个特殊源配置一组特定的 trace listeners。Log writer 会将日志条目传递给我们指定的匹配的 trace listeners。
- 然后,trace listener 使用日志格式化器将日志条目中的信息转换为适当的格式,例如格式化文本或二进制,并将结果写入特定于 trace listener 类型的输出。根据 trace listener 类型,输出可以进入文件、数据库、WMI、Message Queuing(也称为 MSMQ),或作为电子邮件消息。
Logging Application Block 的源模式
3. 实际步骤
让我们关注 Logging Application Block 的实际部分。
安装 MSMQ 后;创建一个非事务性的 private
队列,所有日志消息都将发送到该队列。事务性队列也可以工作,但不是必需的,因为 MSMQ Distributor 不使用分布式事务。
创建新的消息队列
- 在 **控制面板** 中,双击 **管理工具**,然后双击 **计算机管理**。
- 展开 **服务和应用程序**,然后展开 **Message Queuing**(仅在 MSMQ 成功安装后可用)。
注意:队列可以是 public
或 private
的,具体取决于通知应用程序的要求。我们的示例应用程序演示了一个 private
队列。
- 右键单击 **Private Queues**,然后单击 **New**。
- 为私有队列输入名称,然后单击 **OK**。
创建队列后,转到属性,并根据需要设置权限,以确定谁对队列拥有什么访问权限。
创建新的 Visual Studio 项目
- 打开 Visual Studio。
- 选择 **New | Project | Visual C# | Windows Forms Application**。
- 将项目命名为适当的名称,例如
EntLibLoggingExampleOne
。
添加对 Enterprise Library Logging Assembly 的引用
- 在 Solution Explorer 中,右键单击项目节点并选择 **Add Reference**。
- 浏览并选择 Microsoft.Practices.EnterpriseLibrary.Logging.dll。
- 点击“确定”。
为应用程序配置日志记录
虽然我们可以通过代码配置 Application Logging Block,但最好通过 XML 配置文件进行配置。任何更改都不需要我们重新编译代码。此外,我们可以轻松地通过 Enterprise Library Configuration Tool - **EntLib Config .NET 4** 创建配置。现在向项目中添加一个应用程序配置文件,然后向其中添加配置信息。
- 在 Solution Explorer 中,右键单击项目节点并选择 **Add | New Item**。
- 选择 **Visual C# Items | General | Application Configuration File**
- 将文件名 App.config 保留原样
- 单击 Add
- 在 XML 编辑器中打开 app.config(在 Solution Explorer 中双击它),并注意它是空的。你应该看到类似这样的内容
- 关闭 app.config。
- 在 Solution Explorer 中右键单击 app.config 并选择 Edit Enterprise Library V5 Configuration,如下图所示
- Enterprise Library Configuration V5 Editor 打开。
- 单击 **Blocks | Add Logging Settings**(如果 Logging Settings 尚不存在)
- 新的 Logging Application Block 节点已添加到配置编辑器中。单击 + 号添加新的类别、过滤器、trace listeners 和消息格式化器。块的布局将与此类似
- 关闭 app.config 可视化编辑器窗口。
- 在 Solution Explorer 中双击 app.config 在 XML 编辑器中打开它。我们可以看到为日志块添加的配置 XML。
向应用程序添加日志记录代码
应用程序已配置好以进行日志记录,并且依赖项已链接。
- 在设计模式下,向 Form 添加一个按钮。
- 在代码编辑器中打开 Form1.cs。
- 在代码文件顶部添加突出显示的
using
语句。using Microsoft.Practices.EnterpriseLibrary.Logging;
- 在任何按钮的单击处理程序中,添加代码。实例化一个新的
LogEntry
对象,并将其Message
属性设置为适当的内容,例如“Starting up the application”。 - 使用
static Logger.Write()
方法提交LogEntry
进行日志记录。 - 我们的代码应该类似于此
private void myButtonWriteToLog_Click(object sender, EventArgs e)
{
LogEntry logEntry = new LogEntry();
logEntry.Message = "Starting up the application";
Logger.Write(logEntry);
Logger.Write("Hello Error", "Error");
Logger.Write("Hello Message", "None", 1, 01, TraceEventType.Information);
Logger.Write("Hello Crash", "General", 1, 02, TraceEventType.Error);
Logger.Write("Hello Crash", "Error", 1, 01, TraceEventType.Error, "Ravi");
}
运行应用程序并验证日志记录
- 按 CTRL+F5。
- 单击按钮以运行单击处理程序。
- 打开配置的平面文件——“C:\trace.log”。
- 日志文件的内容应如下:
4. MSMQ Distributor Service
应用程序通常需要将多个来源的日志条目发送到同一个目的地。Logging Application Block 利用 **Message Queuing**(也称为 **MSMQ**)来实现这一点。通过将多个应用程序配置为使用同一个消息队列,我们可以在中央位置处理日志条目。
要将日志条目分发到中央目的地,请将应用程序配置为将日志条目写入消息队列 trace listener。当应用程序将日志条目发送到 Logging Application Block 时,它会将日志条目放入 Message Queuing 队列。 **distributor service** 作为一个 **Windows service** 运行,可以运行在与应用程序相同的计算机上,也可以运行在远程计算机上。它会轮询队列以查看其中是否有任何日志条目。轮询间隔由配置决定。如果队列中有日志条目,distributor service 将使用 Logging Application Block 的实例将消息转发给 trace listener(s)。trace listener(s) 将日志条目写入目的地,例如事件日志或平面文件。
distributor service 要求所有日志条目都使用 BinaryLogFormatter
类进行格式化。如果服务无法解释该条目,它将向应用程序事件日志记录错误并关闭。
下面的示意图说明了多个应用程序如何使用 distributor service 将日志条目发送到中央位置。
Logging Application Block 的每个实例都使用消息队列 trace listener(MsmqTraceListener
类)的实例将日志条目发送到单个目标队列。distributor service 轮询队列并使用 Logging Application Block 的另一个实例将日志条目定向到适当的 trace listeners。
主要流程如下。所有计算机应在同一域中才能实现此功能。
- A 机器上的应用程序调用 Enterprise Library 日志 API 来写入日志条目。
- Enterprise Library 使用二进制格式化器序列化条目,并将序列化的日志条目放入本地 MSMQ 出站队列。
- MSMQ 将条目作为消息发送到 C 计算机上的目标队列。
- MSMQ distributor service 轮询目标队列。
- MSMQ distributor service 读取消息并将其反序列化回日志条目。
- MSMQ distributor service 调用 Enterprise Library API 来记录条目。
- MSMQ distributor service 从队列中删除条目。
MSMQ Distributor Service 在 Enterprise Library 框架中已准备就绪,我们只需要 **配置、安装和运行** 它。它需要两个文件,这些文件将与 Enterprise Library 包一起安装在“..\Microsoft Enterprise Library 5.0\bin”文件夹中——**MsmqDistributor.exe** 和 **MsmqDistributor.exe.config**。
配置
MSMQ distributor service 的配置与 Logging Application Block 的配置几乎相似。**此外**,服务必须读取 **消息队列** 才能读取日志。
- 在 Enterprise Library Configuration V5 Editor 中打开 MSMQDistributor.exe.config。
- 单击 **Blocks | Add Logging Settings**(如果 Logging Settings 尚不存在)
- 新的 Logging Application Block 节点已添加到配置编辑器中。单击 + 号
添加新的类别、过滤器、trace listeners 和消息格式化器。块的布局将与此类似 - 关闭 MSMQDistributor.exe.config 可视化编辑器窗口。
- 双击 MSMQDistributor.exe.config 在 XML 编辑器中打开它。我们可以看到为日志块添加的配置 XML。
- 这里我们有一个额外的设置节点,称为“
msmqDistributorSettings
”。我们必须手动编辑这些详细信息,因为我们无法使用配置控制台进行操作。 - 将
msmqPath
属性更改为匹配指定队列的名称。默认名称为 **".\Private$\entlib"**。 - “
queueTimeInterval
”是检查消息队列中日志条目的时间间隔(以毫秒为单位)。 - MsmqDistributor.exe.config 文件包含一个“
serviceName
”属性。安装 distributor service 后,请勿更改此名称。如果这样做,我们将无法卸载该服务,因为系统将尝试卸载具有新serviceName
值的服务。 - 更改
serviceName
属性后,我们也无法重新启动该服务。当 Windows 重新启动服务时,它首先会启动服务停止,然后启动服务。如果更改serviceName
属性,Windows 将无法启动服务停止,因为它会查找具有新名称的服务。 - 我们应该使用
serviceName
属性在同一台计算机上运行 **多个 distributor service 实例**。以下过程显示了如何执行此操作。 - 将 Msmqdistributor.exe 文件和 MsmqDistributor.exe.config 文件复制到多个目录。
- 在每个目录中更新 MsmqDistributor.exe.config 文件,使其具有唯一的服务名称。
- 为每个副本运行 Installutil 工具。这将使 distributor service 的每个副本都具有与相应配置文件中相同的服务名称。
distributor service 在向事件日志记录消息时使用 **服务名称作为 trace source**。**此日志始终是应用程序事件日志**。
安装
配置完成后,我们可以将服务安装到系统中;步骤如下
- 打开 Visual Studio 命令提示符。在命令行中,键入 **installutil -i msmqdistributor.exe**。(安装程序工具 **Installutil.exe** 位于 Framework 目录中。例如 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727。)
- 运行安装程序工具时,系统会提示输入 **用户名和密码**,用于运行 Message Queuing 服务的帐户。
- 要卸载 distributor service,请在命令行中键入 **installutil /u msmqdistributor.exe**。
- 这应该会为安装和卸载分别提示相应的消息。
启动 Distributor Service
以下过程启动 distributor service。
- 在任务栏上,单击开始,单击控制面板,双击管理工具,然后双击服务。
- 右键单击 distributor service,然后单击启动。
验证日志记录
- 运行前面讨论过的应用程序,该应用程序会将日志记录到消息队列和平坦文件中。
- 单击按钮以运行单击处理程序。
- 打开 Windows 事件查看器。
- 打开应用程序事件日志并验证最近的事件;它应该类似于以下内容
5. 配置时需要记住的几点
以下是 Logging Application Block 配置中的一些重要设置
- Recoverable - 这是指示消息是否应持久化到磁盘。如果设置为
false
,则队列中的消息在关闭后将不会保留。 - TimeToReachQueue - 如果目标队列不可达,消息在出站队列中应保留多长时间。超过该时间后,如果
useDeadLetterQueue
设置为true
,则消息将进入系统 Dead-letter Queue,否则将被丢弃。消息将位于源计算机的 Dead-letter 队列中。默认约为 250 年。Dead-letter 队列是系统生成的队列,用于存储未能传递的消息。 - TimeToBeReceived - 消息在目标队列中应保留多长时间。如果 MSMQ Distributor service 未运行,消息可以在那里保留很长时间。消息将位于目标计算机的 Dead-letter 队列中。
- UseAuthentication - 这是启用消息身份验证,并且应与队列的身份验证设置匹配。发送方和接收方都需要更新的证书。
6. 参考文献
- Enterprise Library Visual Studio 2008 集成文档 (MSDN)
- http://entlib.codeplex.com/
- http://www.google.co.in/
7. 历史
- 2011/08/12 - 初始帖子