You came, you saw, and you asked some probing questions about microservices messaging—so we wanted to share some more insights.
During our recent NServiceBus webinar, our Chief Architect Jimmy Bogard talked about the challenges of moving to messaging, then walked us through some implementation patterns. The questions that viewers submitted at the end of the talk became catalysts for deeper discussion. So as Jimmy jetted to NDC Oslo this week to talk about distributed transactions, he also dug into some of your messaging queries. The video addresses issues that merited demos, like how you can share events projects, the pros and cons of different publishing approaches, how to inform a user when a “payment” fails, and where you place validation. Below, he dives into the whys, whats, and hows of messaging with NServiceBus, and includes links to helpful resources.
More on microservices messaging w/ NServiceBus
Q: How do you know when to use a Command vs. an Event?
Commands direct some system to perform some action. Events are a fact, typically modeled in some form of a past tense verb.
When we want to direct a system to perform an action, we use a command. When we want to notify other systems that some action has occurred, we use an event. From an SOA/microservice perspective, this means that in order to avoid process coupling between services, we use commands inside a service boundary and events between them.
This is not a hard and fast rule, however, as we can intentionally expose commands for capabilities (such as “print this report” or “send this email” or “bill this customer”).
Q: Is there an automatic retry for the handler that can be configured?
Yes! See the docs on recoverability.
Q: How is the state table created for the saga (placeOrderRequests)? Manually or automatically?
In our example, automagically because we enabled recoverability installers, which creates the required infrastructure on startup. It’s an opt-in behavior, and we can instead use MSBuild to generate the required SQL scripts if we want to create these tables as a separate process.
Q: Is there a tool to visualize the message (events/commands) flow/process?
Yes! This tool from Particular called “Service Insight” shows how messages flow through the system.
Q: Why is it recommended to use Guid(s)?
Mainly because they’re globally unique, so then we don’t have to worry about ID collisions between resources of the same (or different) type.
How much information should an event contain? Is it bad practice to put whole records of data when broadcasting events to downstream systems?
There’s a short answer: Events should contain only what is necessary for the overall system to function, and nothing more. The longer answer would look at coupling between systems, fat vs. skinny events, and more. Large events are not automatically incorrect, but we need to take care we’re not accidentally introducing coupling and over-exposing state.
Q: In the .Net Microservices book that came out last year, they were doing domain events through MediatR and infrastructure events through Azure Service Bus, where you can add higher level abstraction for ease of use like NServiceBus. How do you feel about this separation of events?
I like it. Domain events are internal to a service boundary, and infrastructure/integration events are between service boundaries. Often we have to “republish” a domain event as an infrastructure event, and this activity can be viewed as an “Anti-Corruption Layer” in domain-driven design terms. We don’t want to directly expose our state outside our service boundary, nor our domain events.
Q: NServiceBus Saga employs the concept of Timeout. Can you explain that please?
Not in a single written answer :). But the NServiceBus docs on timeouts do a great job of explaining the details.
Q: Should/could you be using NServiceBus for HTTP GET from an API ?
Typically, no. GETs are typically for synchronous requests for information. Adding an asynchronous message to the mix would create a clunky interaction. However, I do have NServiceBus handlers requesting data from web APIs to perform some work.
Q: What is the performance impact of sagas? Is there an in-memory alternative or can one specialize the storage to use something with less latency than a read/write interaction with a relational store?
Not much that I’ve seen. The point of sagas is to have a long-running process, and an in-memory store implies a short-running process. If I want a short-running process, I wouldn’t use durable messages or sagas. Saga storage can be specialized, but in practice, I don’t make this choice on database performance concerns, as we’ve seen performance numbers being roughly equal.
Q: The Saga database table you showed, I guess that’s something customized?
It’s built by the persistence we choose, and each persistence option will set up the saga storage differently.
Q: How do I map saga data on multiple properties to find saga from persistence?
Saga-finding logic can be customized: Refer to the docs for more info.
Q: Can messages deal with uploaded files? For example, an import file?
Yes! In fact, I’ve got a presentation from a few years back that goes into more details and options.
Q: You touched on how this async pattern changes the way we present UI feedback to a user. Could you talk a bit more about how you think about when to use synchronous vs. async handling, and how it changes your UI design thinking?
It’s brought UI design thinking—i.e., a focus on User Experience (UX)—much more to the forefront than I’ve seen in the past. As we incorporate async into our systems, how we present this to the end user matters more than ever. For inspiration, I pay attention to the UX of async systems when using different websites, to see what works well and doesn’t. The patterns are all there, it’s just up to us to choose the right one for our users.
Q: There’s an argument stating that pure event-driven architectures tend to get messy and you lose the overview. What is your opinion on workflow solutions?
I’ve used both solutions—even in a given system. Workflows are great for orchestration when I’m explicitly controlling the steps to be done. I also find workflow products can often connect to devices or integration points that I wouldn’t easily be able to author myself. Sagas can be difficult to visualize, so I typically use sequence diagrams to convey the overall flow. For what actually occurs within a saga, I use the Service Insight tool to show me how a saga behaved in production.