Transcript gojko.net
Asynchronous .NET applications with NServiceBus David de Florinier ([email protected]) Gojko Adzic ([email protected]) Skills Matter 27/11/2008 Don't be afraid of messaging Fire and forget... http://www.sxc.hu/photo/1084274 Fire and forget Use when the second part of a process has to be completed, but we don't really have to wait for it to finish. This typically involves an external system or batch processing. Resilience Easier to test Option to go offline Just leave it there when you're done http://www.sxc.hu/photo/319039 Just leave it there when you're done Use when the second part of a process is slow or talks to an external system, but completing the task is important to continue the work. Better UI responsiveness Performance Better resource usage Share the load http://www.flickr.com/photos/library_of_congress/2179123671 / Share the load Use when lots of different agents can submit or process work. Decouple workers and requesters. Performance Scalability More flexible Easier to extend The key to efficient async architectures! http://www.sxc.hu/photo/1035790 Who? ... What? ...Where? Written by Udi Dahan It is an open source communications framework Get it from http://www.nservicebus.com Released under the Apache Licence 2.0 Current Release is 1.8 Getting Started Download from http://www.nservicebus.com/Downloads.aspx Extract the files from the zip, then build using build.bat (this uses msbuild) The assemblies will now be in the build folder (and subfolders) Look through the Sample projects, these cover all the simple usage cases (for Spring) What is included... IBuilder Various parts of the framework (e.g. passing messages to handlers) use a service locator pattern. This is done using the IBuilder interface An implementation using Spring is provided: ObjectBuilder.SpringFramework An example of a implementation for Castle Windsor is in the Demo source ITransport Responsibility for sending and receiving messages is delegated to a transport component Unicast Implementations for MSMQ and Http are provided There is an IMulticastTransport interface, but there are no implementations provided IMessageSerializer Responsibilty for serialization of messages is delegated to a serialization component Implementations for Binary and Xml serialization are provided Has the following methods void Initialize(params Type[] types); void Serialize(IMessage[] messages, Stream stream); IMessage[] Deserialize(Stream stream); IBus The entry point for your code Send, Subscribe, Unsubscribe, Publish IUnicastBus and IMulticastBus interfaces inherit from IBus, Use IUnicastBus with IUnicastTransport Use IMulticastBus IMulticastTransport Publish/Subscribe Messages should implement the IMessage marker interface Use IBus.Publish(IMessage) Use IBus.Subscribe(Type[,predicate]) Message handlers implement IMessageHandler<T> Implement IBuilder interface to create an handler builder if not using Spring.Net ISubscriptionStorage Needs to be configured for publishers Persistence and retrieval of subscriptions is delegated to ISubscriptionStorage Db and Msmq implementations are provided Db implementation allows multiple publisher instances to share one subscription store Publish/Subscribe config Always needed Transport : NumberOfWorkerThreads, IsTransactional, InputQueue Bus: ITransport, IMessageSerializer. On Publisher: SubscriptionStorage : persistence for subscriptions Bus: ISubscriptionStorage On Subscriber Transport : NumberOfWorkerThreads, IsTransactional, InputQueue no need for ISubscriptionStorage. IBuilder must be able to build Handlers Bus: MessageOwners: where subscription messages are sent Bus: AddTypesFromAssembly for handler types Publish Subscribe demo Full Duplex Use IBus.Send(IMessage).Register(Callback) to make asynchronous request Use IBus.Reply(Response) to send response Full Duplex code Sending message from the client bus.Send(["worker@localhost", ]msg).Register(callback, msg); Handling the message on the server _bus.Reply(response); Handling the callback on the client private void callback(IAsyncResult ar) { .... CompletionResult result = asyncResult.AsyncState as CompletionResult; Message request = result.State as Message; ... foreach (var message in result.Messages) { ...} .... } Full Duplex demo Saga Framework for long lived message workflows Saga Messages implement ISagaMessage Implement ISaga<T> to handle saga messages NserviceBus.Testing.Saga contains Mock objects for use in unit tests ISagaPersister The responsibility of persisting and rehydrating Saga entities is delegated to a class implementing ISagaPersister DbBlobSagaPersister implementation provided ISaga<T> Saga Enitity, which will handle the various steps in the saga workflow, will implement ISaga<T> for each workflow step Also a class extending SagaMessageHandler may be used. This will typically override the Handle and NeedToHandle methods. The SagaMessageHandler uses ISagaPersister to rehydrate the ISaga<T> implementation, and call it's Handle method Saga interaction Saga Demo Distributor A way of scaling costly transactions Workers report for work Distributor sends work to first available worker When workers have completed, they report for work again An executable is provided Conclusions Positives Source code is well structured and easy to understand Main objects can be extended, flexible architecture Has performed well in load tests Few dependencies Negatives There is little documentation Some alternatives? ActiveMQ and NMS http://activemq.apache.org/nms.html SimpleServiceBus http://www.codeplex.com/SimpleServiceBus MassTransit http://code.google.com/p/masstransit/ Links http://www.nservicebus.com http://www.udidahan.com http://ayende.com/Blog/archive/2008/03/24/NSe rviceBus-Review.aspx http://gojko.net Next events TDD in .NET, 17/Dec OpenSource .NET Exchange 22/Jan Fitnesse.NET tips and tricks, 17/Feb For more info: http://ukdotnet.ning.com/ Questions?