Files
ObsidianJournal/Training/Advanced Distributed Systems/Advanced Distributed Systems Design - Module 4 - Messaging Patterns continued.md

3.6 KiB

Web Services with messaging
Separate pieces of logic behind their own messages.  This is so that, for example, if the database transaction fails, it won't continually try to hit the web services, or vice versa.  If you separate the operations behind two different messages, then the database transaction can be retried on its own and the web service call can be retried on its own. Instead of trying to make web services idempotent and re-engineer everything that message does, just change the interaction between your service and the web service to take place over messaging instead of HTTP calls. Use client-generated IDs (GUIDs) so that data can be uniquely identified throughout the business process and de-duped after failures and retries. Request/Response with messaging
Response is nothing different than the request.  It's just a message going back the other way.  It goes back to the return address. To make this work, you have to have a correlation ID so that the response an endpoint gets can be correlated to a specific message it sent.  Otherwise, after sending 100 messages, who knows which message the response relates to? With NServiceBus, you can provide a callback that is executed when the return message is received.   Multiple Responses
We can send multiple responses back to the requester by simply using the same correlation ID.  For example, this would be useful to report status to a UI on a long-running process. Subscribe - Publish
Subscribe as a request, publish as a series of messages coming back to that subscriber over time.  Logically, this is exactly the same as request, multi-response. The subscribe request doesn't actually need to send a message to the publisher.  It depends on the queuing technology.  If it supports pub/sub natively, then it's just a configuration of the broker to tell all subscribers when a message is published to a certain topic. Pub/sub is not multicast.  If a subscriber is down when a message is published, it will not miss the message.  It will be reliably delivered once the subscriber is up. Important difference: are subscribers independent subscribers (all should get event) or are they scaled out instances of the same logical subscriber (any one, but only one, should get the event)?  NServiceBus will pick one instance to send the published message to.  If you're doing something like invalidating a cache at multiple web frontends (therefore, all would have to get the event to invalidate their cache), don't use pub/sub!  It's a distributed cache--so, use a distributed cache instead of individual caches on each web server.  That is, use the technology that already solves the problem for you. Exceptions
We assign too much emergency to exceptions being thrown.  We need to change our mindset to allow transient error states in our systems that the system can recover from.  Do we need to catch every exception and throw our own custom exceptions and log our own custom messages?  Or can we just allow the exception to happen, allow the messaging to retry and only panic when message end up in the error queue. Should we really check dependency-injected objects for null?  Our system will fail consistently if we have it misconfigured to not inject dependencies. The error queue is your true source of problems--not exceptions.  Once something has failed after retries, it truly is a problem. Summary
You can get into a case where instead of one, monolithic ball of mud, you have 700 tiny balls of mud that send thousands of messages and subscribe and publish and you have no idea what's going on.  This is where boundaries come in and are important!