NServiceBus入门:启程(Introduction to NServiceBus: Getting started)
原文地址:https://docs.particular.net/tutorials/intro-to-nservicebus/1-getting-started/
侵删。
最好的学习NServiceBus的方法就是做一个真实的Demo。在做的过程中你将会学到软件背后的架构概念,和它的功能。在这个教程中,你将会建立一个电商系统的后台。你将会学习到如何在进程间异步发送message,如何使用发布者订阅者模式来解耦业务,以及使用可靠的信息传输方式来在发生错误之后进行重试。
这个教程分为五个课程,每一个都可以在半个小时左右完成——你可以利用午休的时间来完成。
在第一节课中,大概要花10-15分钟,你会学习到如何配置一个NServiceBus 的环境然后创建你第一个endpoint。
开始之前的准备
NServiceBus 只需要.NET Framework和队列架构服务就能够部署。
尽管NServiceBus能够支持.NET Framework4.5.2或者以上的版本,这个教程使用的是Visual Studio 2015 和 .NET Framework 4.6.1,他们包含了一些有用的异步API。
NServiceBus 需要队列架构服务(作为transport)来作为传输message的管道。这个教程默认使用Microsoft Message Queuing (MSMQ)来作为transport,MSMQ被包含在几乎所有版本的windows系统中,但是不会默认安装。
如果MSMQ在你的环境里面不能使用,SQL Server Transport 也可以作为一个替代的transport选择。想要使用SQL Server而来替代MSMQ的话,可以参阅SQL Server transport setup instructions。这个教程里面会通过标注的方式来展示使用SQL和MSMQ作为transport的不同地方。
想要安装MSMQ到你的电脑上面,你有两个选择:
1.Download and run the Particular Platform Installer(下载和运行特定平台的安装包)。
2.Install and configure MSMQ manually(手动安装和配置MSMQ)。
(略)
练习
现在让我们小试牛刀。
创建一个解决方案
首先,我们建立一个基本的解决方案然后添加我们需要的依赖项。
1.在vs中,新建一个新的项目然后选择控制台应用程序。
2.把项目名字设置成ClientUI。
3.把解决方案名字设置成RetailDemo。
接下来,我们需要添加NServiceBus NuGet 包作为依赖项。在Nuget包管理工具控制台里面,输入:
Install-Package NServiceBus -ProjectName ClientUI
这回将NServiceBus.Core 程序集添加到项目之中。
如果你使用SQL Server transport,你还需要安装NServiceBus.SqlServer 。参见 Using the SQL Server transport - Adding the NuGet package 来获得更多详细信息。
这些依赖项安装好了之后,我们可以开始写代码了。
创建一个endpoint
现在我们已经可以开始创建一个endpoint了。endpoint是一个用来发送和接受message的逻辑部件。endpoint寄宿在一个进程中,在这个教程中主要是控制台应用程序,但是也可能是一个web应用程序或者其他的.NET进程。
由于控制台应用程序的局限性,我们需要添加一些使用async/await的模板似的代码。
在Program.cs中,修改代码如下:
class Program { static void Main() { AsyncMain().GetAwaiter().GetResult(); } static async Task AsyncMain() { } }
先添加下面的代码到你的程序中,然后我们会一行一行地分析他们的作用。
添加这些代码到AsyncMain方法中:
static async Task AsyncMain() { Console.Title = "ClientUI"; var endpointConfiguration = new EndpointConfiguration("ClientUI"); var transport = endpointConfiguration.UseTransport<MsmqTransport>(); endpointConfiguration.UseSerialization<JsonSerializer>(); endpointConfiguration.UsePersistence<InMemoryPersistence>(); endpointConfiguration.SendFailedMessagesTo("error"); endpointConfiguration.EnableInstallers(); }
现在我们一行一行地分析每一步都在做些什么。
控制台标题
Console.Title = "ClientUI";
当运行同一个解决方案里面的多个控制台应用程序的时候,给每一个应用程序一个名字来让它们更好地分辨。这个控制台应用程序的标题就使用ClientUI。在接下来的课程中,我们会扩展这个解决方案来拥有更多的控制台应用程序。
endpoint配置
var endpointConfiguration = new EndpointConfiguration("ClientUI");
我们在EndpointConfiguration 类中配置和决定我们的endpoint如何工作。“ClientUI ”是这个endpoint的名字,会作为endpoint的逻辑标识符,然后会按照这个命名惯例来给其他相关的服务取名,例如这个endpoint监听的预处理message输入队列。
Transport
var transport = endpointConfiguration.UseTransport<MsmqTransport>();
这个配置定义了NServiceBus用来发送和接受message的transport。我们现在用的是Msmqtransport,这个transport已经绑定在NServiceBus 核心库之中。所有其他的transport都需要不同的NuGet安装包。
像上面一样在一个变量中获取transport配置会让我们在第三节课中开始定义message路由规则的时候更加容易。
如果使用SQL Server 作为transport,你必须使用SqlServerTransport 然后提供一个数据库连接字符串。参见Using the SQL Server transport - Configuring the transport 来获得更多详情。
序列化器
endpointConfiguration.UseSerialization<JsonSerializer>();
当发送message的时候,endpoint需要将message对象序列化成流,然后在接收端将流反序列化成message对象。序列化器的选择决定了序列化的格式。系统中的每一个endpoint都需要相同的序列化器来保证他们能够正常解析相互之间的message。
这里我们选择了JsonSerializer ,因为JSON是一个合理而有效的消息封装机制,同时易读性也很强。当使用JSON的时候,它也可以很容易地和其他平台的其他系统兼容。
Persistence
endpointConfiguration.UsePersistence<InMemoryPersistence>();
一个Persistence用来在处理message的时候持久化一些数据。我们会在以后的课程中探讨更多关于这个的原因,但是目前,我们会使用一个implementation that stores everything in memory(数据内存持久化方式)。这种方式有一个优点就是,在开发的时候允许我们能够在每次运行的时候保证一个干净的初始环境。当然,如果endpoint关闭的时候,所有的持久化信息都会丢失,这个在生产过程中是不安全的,所以我们将会将在部署之前将它替换成其他的持久化方式。
错误队列
endpointConfiguration.SendFailedMessagesTo("error");
在处理message的过程中可能会产生一些由于各种各样原因造成的错误。可能是由于代码的bug,也可能是由于数据库死锁,或者在message中包含其他无法预料的数据。如果遇到一些不是太严重的问题,可以对重试请求来解决,但是一些非常严重的问题,这些message会在队列顶部,不断地重试会导致阻塞。这种“有毒”的message会阻塞所有在它之后的message。当这种情况发生的时候,NServiceBus 需要能够把它晾在一边以让其他工作能够进行。这个队列就是error队列。我们在Lesson 5: Retrying errors里面更详细地讨论恢复机制。
Installers
endpointConfiguration.EnableInstallers();
这个配置告诉endpoint在运行的时候要启动installers。Installers用来配置endpoint正常运行的所有配置。最常见的例子就是创建必要的队列,例如endpoint的用来接收message的输入队列。
启动
在AsyncMain 方法尾部的配置代码的后面,添加下面的代码,这些代码会开启endpoint,并且保持它运行直到我们按下回车键退出。
var endpointInstance = await Endpoint.Start(endpointConfiguration) .ConfigureAwait(false); Console.WriteLine("Press Enter to exit..."); Console.ReadLine(); await endpointInstance.Stop() .ConfigureAwait(false);
在这个教程中我们会一直使用.ConfigureAwait(false) await task,目的是为了avoid capturing and restoring the SynchronizationContext.(获取并且重建同步上下文)。
endpoint会根据EndpointConfiguration 类中定义的配置来进行初始化。一旦endpoint启动,任何对配置信息的改变都不会被应用。
当你第一次运行endpoint的时候,endpoint会做这些工作:
- 输出它的日志信息,这些信息会写入到文件,也会展示在控制台上面。NServiceBus 也会在有多重层次的日志,因此你可以change the log level (改变日志等级),从INFO到DEBUG来获得更多的信息。
- 输出status of your license.(你的证书状态)。
- 尝试添加当前用户到“性能监视用户”组,这样它可以输出performance counters (性能信息)来追踪它的性能和进程。
- 如果不存在的话,添加一些队列:
- error
- clientui
- clientui.retries
- clientui.timeouts
- clientui.timeoutsdispatcher
现在可以看看你的队列列表了。有很多查看MSMQ队列和信息的方式供你选择。除了上面介绍的这些队列之外,你也可以看到一个error.log 队列和particular.servicecontrol 启动的队列,如果你在安装特定的服务平台的时候安装了服务控制实例的话。
如果你使用SQL server transport,那么久看看你的SQL数据库,在数据库中,NServiceBus 会在一个单独的数据表中建立上面提到的队列。
总结
在这节课中,我们创建了一个简单的endpoint,并且保证它正常工作。在下节课,我们会定义一个message,一个message handler然后把message发送到message handler然后看看它如何被处理。