nservicebus workshop presentation
DESCRIPTION
Espen Ekvang and I had a one day workshop internally at BEKK, and this is the presentation we made for the workshop.TRANSCRIPT
NSERVICEBUS
Inspired by: The course authored by Udi Dahan
Oslo/Fagdag
Espen Ekvang/Tomas Jansson
01/03/2013
2AGENDA
• Intro
• Messaging and queues
• Testing
• SOA
• Saga
4INTRO
• Fallacies of distributed computing
• Why NServiceBus?
• Bus vs. Broker
• Service orientation
• Excercises
5FALLACIES OF DISTRIBUTED COMPUTING
1. The network is reliable
2. Latency isn’t a problem
3. Bandwidth isn’t a problem
4. The network is secure
5. The topology won’t change
6. The administrator will know what to do
7. Transport cost isn’t a problem
8. The network is homogeneous
Cant’ assume WHEN the message will arrive,
IF AT ALL
6WHY NSERVICEBUS
1. The network is reliable
2. Latency isn’t a problem
3. Bandwidth isn’t a problem
4. The network is secure
5. The topology won’t change
6. The administrator will know what to do
7. Transport cost isn’t a problem
8. The network is homogeneous
NServiceBus addresses the first five directly
The most developer-friendly service bus for SOA on .NET
7BUS VS. BROKER
Buss.dll
App
Buss.dll
AppBuss.
dll
App
App
App App
Broker
• Bus is not necessarily physically separate• Simpler; no routing or service fail over• No single point of failure
8TENETS OF SERVICE ORIENTATION• Services are autonomous• Share contract & schema, not class or
type• Boundaries are explicit• Compatibitility is base on Policy
9LAYERS & COUPLING
UI
BL
DAL
DB
SalesShippin
gCRM
Tight coupling
Loose coupling
Referential Integrity
Reintroduces coupling
10WHEN CAN I WRITE SOME CODE?
• Getting started• New class library
• Install-Package NServiceBus.Host
• Logging• NServiceBus uses log4net, you can configure logging in app.config
• Default output is console
11EXERCISES
HELLO WORLD
LOGGING
12MESSAGING AND QUEUES
• Store & forward
• Dangers of store & forward
• Request/Response
• Messaging and NServiceBus
• Exercises
13
SERVER
STORE & FORWARD
MSMQ
OUTGOING INCOMING
CLIENT
MSMQ
OUTGOING INCOMING
Store & Forward writes to disk
Resilient in the face of failures
14DANGERS OF STORE & FORWARD
• If target is offline for an extended period of timemessages can fill up the disk• Can cause a server to crash
• Especially problematic in B2B integration• 1 MB/message, 100 message/sec = 6GB/minute
• Solution – discard messages after a while• Use [TimeToBeReceived("00:01:00")] on the message definition
15REQUEST/RESPONSE
SERVER
MSMQ
OUTGOING INCOMING
CLIENT
MSMQ
OUTGOING INCOMING
Client can’t assume when a response will arrive, if at all
Equivalent to 2 one-way messages
16REQUEST/RESPONSE
• Message is sent from the server to the client’s queueIf the client is offline, message sits in the server machine’s outgoing queue
• Client is not blocked until response arrives
• If two requests were sent, responses may arrive out of order
17WARNING! THIS IS NOT RPC
• Do NOT try to implement regular request/response patterns on top of messaging
• The client should be designed so that it can continue operating if a response never comes
Differences from RPC
• RPC is easy to code• After invoking a web service• Next line of code assumes we’ve got a response
• RPC problems• Can’t reason about the time between one line of code and another
• Messaging makes this all explicit
18MESSAGING AND NSERVICEBUS
SERVER
MSMQ
OUTGOING INCOMING
CLIENT
MSMQ
OUTGOING INCOMING
Transaction
19DEFINE A MESSAGE
• Preferably inherit from IEvent or ICommand
• Use IMessage when replying using Bus.Reply()
• Also possible to define your own convention• Configure.DefiningMessagesAs(t=>MyOwnConvention(t))
• Add properties like a regular class/interface
• Keep contract definintions in their own assembly/project
public class MyEvent: IEvent {}
20INSTANTIATE A MESSAGE
• var myMessage = new MyMessage();
• var myMessage = Bus.CreateInstance<MyMessage>();
21SEND A MESSAGE
Bus.Send(messageObject);
Can instantiate and send together (useful for interfaces):
Bus.Send<IMessage>((message) =>
{
message.Prop1 = value1;
message.Prop2 = value2;
});
22SPECIFY DESTINATION
1. Bus.Send(destination, messages);
Requires that application manages routing
2. Configure destination for message type.
In <UnicastBusConfig>, under <MessageEndpointMappings> specify one of the following:
- <add Messages="assembly" Endpoint="destination"/>- <add Messages="type" Endpoint="destination"/>
3. Specify destination using
- QueueName@ServerName , or
- Just QueueName for the same machine
23HANDLE A MESSAGE
Write a class that implements IHandleMessages<T> where T is a message type
public class MyHandler : IHandleMessages<MyMessage>
{
public void Handle(MyMessage message)
{
}
}
Remember to specify in <UnicastBusConfig>, under
<MessageEndpointMappings> one of the following:
- <add Messages="assembly" Endpoint="source"/>- <add Messages="type" Endpoint="source"/>
24CONFIGURING AN ENDPOINT
When configuring an endpoint inherit from
1. Using AsA_Client will
- use non-transactional MsmqTransport- purge its queue of messages on startup- processes messages using its own permissions, not those of the message sender
2. Using AsA_Server will
- use transactional MsmqTransport- not purge its queue of messages on startup, hence fault-tolerant- processes messages using the permissions of the sender (impersonation)
3. Using AsA_Publisher will
- extends AsA_Server - indicates to the infrastructure that a storage for subscription request is to be set up
25EXERCISES
ONE-WAY MESSAGING (CLIENT)
PROCESSING MESSAGES (SERVER)
EXCEPTIONS
26UNIT TESTING MESSAGE HANDLERS
Available from NuGet using
Install-Package NServiceBus.Testing
Provides the ability to set expectations around how message handlers handle messages
• Expect: Send, Reply, Publish, etc...
Test.Initialize();
Test.Handler<MyHandler>()
.ExpectPublish<MyMessage>(message => message.Prop1 == value1)
.OnMessage<SomeEvent>(someEvent =>
{
someEvent.Prop1 = inputValue1;
});
27EXERCISE
UNIT TESTING
28SAGA
• Definition
• Saga declaration
• Saga ending
• Saga testing
• Exercise
29SAGA - DEFINITION
A Saga:
• Is a pattern for implementing long-lived transaction by using a series of shorter transactions
• Holds relevant state to needed to process mulitple messages in a ”saga entity”
• Are initiated by a message (event/command)
30SAGA - DECLARATION
public class MyPolicy : Saga<MyPolicyData>,
IAmStartedByMessages<MyMessage1>,
IHandleMessages<MyMessage2>
{
public void Handle(MyMessage1 order)
public void Handle(MyMessage2 order)
}
• Methods are like regular message handling logic• Sagas can be started by multiple messages
(IAmStartedByMessages<T>)• First messages should start saga, following messages should be
processed by the same one
31SAGA – DECLARATION CONT.
public class MyPolicyData : ISagaEntity
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
}
32ENDING A SAGA
MarkAsComplete();
• Can call this from any method
• Causes the saga to be deleted
• Any data that you want retained should be sent on (or published) via a message
33UNIT TESTING A SAGA
Test.Saga<MyPolicy>()
.ExpectPublish<Message1>(/* check values */)
.ExpectSend<Message2>(/* check values */)
.ExpectReplyToOriginator<Message3>(/* check values */)
.When(saga => saga.Handle(myMessage));
/* check values */
message => return(message.Data == someValue);
34EXERCISE - SAGAS ROCK
35EXTRA EXERCISES
TIMEOUTCUSTOM XML NAMESPACECONFIGURABLE ROUTINGDEPENDENCY INJECTIONWEB-APP HOSTINGFULL DUPLEXDISTRIBUTION GROUP EXERCISE