Handling user request in Microservice Architecture powered by Messaging inter-communication (f.e. RabbitMQ) - rabbitmq

I'm just starting with Microservice Architecture and investigating how to build that on top of messaging bus.
There is one concern which bothers me right now - how do I handle a simple query-like request from user or when microservice needs some data from other microservice to serve a response? (f.e. getOrderList, or getUserNameById)
I know there is a RPC pattern in RabbitMQ, but everybody is strongly recommending to avoid that (as it brings temporal coupling) and use async communication instead.

Yes, you have to use async communication in order to make sure that services are temporally decoupled. Here is a good series of articles that explains reasoning behind that design decision in-depth.
Also, consider reading about CQRS/ES approach to design microservices, it was an eye-opener for me when I first discovered it.

Related

What is the design pattern for forwarding messages to a centralised object?

What is the design pattern for forwarding messages to a centralised object?
I have to select few messages from UI and forward them to a centralized service like SQS.
What is the most accurate design pattern that can be used for this scenario?
Below is one of the architecture principles used in the modern world pub-sub based interactions between systems. This is based on the assumption that the UI component has the capability of making an API call and act accordingly based on the response received from the backend components.

Is it wrong for a service to be producer and consumer of Rabbit MQ?

I want to create a "Notifications Microservice" that will handle different type of notifications (Google Chat, Email, etc).
For this task, we will create a microservice that contains the logic on how to process these messages, and we'll be using Rabbit MQ to manage the queue.
Now, the question that I have, is if it is possible (or if it is a bad practice) to expose two endpoints in the microservice like this:
registerNotification('channel', $data)
processNotification(Rabbit Message)
So I only have to implement the communication with RabbitMQ in one service, and other services will just register messages using this same service instead of directly talking to RabbitMQ.
This way for each channel I could validate in the service that I have everything that I need before enqueuing a message.
Is this a good approach?
I'd suggest splitting your question into two separate ones. As usual, it depends ... there's pros and cons to either one. Below my points without claiming completeness. Assessing those really depends on your specific needs in the end.
1) Is it a good practice to use a Notification / Event Gateway in front of a message queue (here RabbitMQ)?
Pros:
enforce strong guarantees on message structure / correctness
provide advanced authentication / authorization mechanisms if required
provide convenience if languages in your stack lack first-class client support
abstract away / encapsulate technology choices & deployment considerations from services (publishers)
eliminate routing logic for messages from individual services (though, using available routing topologies in RabbitMQ, it's hard to see any added value here)
Cons:
availability becomes a critical concern for your gateway, e.g. assuming you can guarantee an uptime of four nines per service, you are already down to three nines for the composed system by adding this dependency
added operational complexity
added latency
An alternative consideration here might be to use a library to achieve some of the pros above. Though, this approach also comes with its own cons.
2) Is it a good practice to run both message publishers and consumers in one service?
Pros:
quick (shortcut?)
initially less deployed instances (until you have to scale up)
Cons:
operational requirements for producers and consumers (workers!) are typically very different
harder (and more expensive) to scale the system adequately and fine grained
(performance) metrics become difficult to interpret
consumers might impact producer latency negatively as everything is competing for the same resources
loss of flexibility on the consumer side (quick, low risk deployments)
harder to guarantee availability of producers
I hope this helps to better evaluate your architecture based on your own needs / priorities.

WebApi in Net Core using RabbitMQ

I am very new on RabbitMQ World and Microservices Architecture. I've watched some tutorials on youtube how to use rabbitMQ but there are some questions I would like to ask.
1.) If the client post the data to my api controller and my api controller publish the data into queue, what is the proper way to respond the post request while the data is being processed on rabbitMQ? Because from the tutorial, It just returns "Ok (Http Code 200)" even though the data is not still completed yet.
2.) Can consumer subscribe more than 1 queue? If yes, is there any configuration sample on startup.cs?
3.) Is there any sample using rabbitMQ on .NetCore for "Real World" cases? Please let me know.
Thanks
It's perfectly okey to return 200. That's just one of many tradeoffs for microservices architecture. E.g. from the performance perspective, it's efficient that you can return early with 200 and propagate all the changes asynchronously through the rest of the distributed system. On the other hand, it adds another type of complexity that you need to embrace - Eventual Consistency. This concept kind of describes what you asked about. Let say your client received 200, but if it immediately calls another microservice the client may not see changes introduced by the previous request, because there is a probability that the changes haven't propagated yet. You need to decide whether it's acceptable in your project or not. If not maybe you should redesign how you split your business domain into microservices, trying to group transactionally close to each other entities together in order to mitigate such problems. If you can't really tolerate Eventual Consistency maybe you should give up on microservices for the particular project.
Yes it can, you could for example create an implementation of IHostedService for each queue listening for messages and run them in parallel with your asp net core app by registering them in the starutp.cs
You'll find this in the repository from the below's links. They use RabbitMQ. Although, there's a bit of abstraction which can make it harder to grasp, it's a great implementation with a bonus of being documented in the free ebook.
https://github.com/dotnet-architecture/eShopOnContainers/ - I can't stress enough how this repository helped me with understanding microservices. There's also a free ebook from Microsoft docs about this repo: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/ . They tackle concepts such as Eventual Consistency and asynchronous communication. It's exactly what you look for.

Angular 5 and Message Bus

I have a set of RESTful services that my Angular 5 client uses to perform CRUD and business operations for the application. These are a set of micro services and they use pub/sub message queues to communicate between them, e.g. when a user is created the user server publishes a UserCreated event to the message queue and subscribers can listen for this event and act upon it as required.
Now, this is all good but i was thinking that wouldn’t it be better if the Angular 5 application itself published the event to the message queue rather than making HTTP POST/PUT or DELETE and only make GET requests against the API?
So repeating the example above the Angular 5 client would publish a CreateUserEvent to the message bus (in my case cloud pub/sub), I could then have services subscribe to these events and act upon them. My RESTful services would then only expose GET /users and GET /user/:id for example.
I know that this is doable and I guess what I am describing is CQRS, but I am keen to understand if publishing events to a message bus from the UI is good practice?
The concept of Messaging Bus is very different than Microservices. Probably, the answer to your question lies in the way you look at these two, from architectural perspective.
A messaging bus(whether it is backend specific or frontend specific) is designed in such a way, that it serves the purpose of communication of entities within the confined boundary of an environment, i.e. backend or frontend.
Whereas on the other hand, microservices architecture is designed in such a way that, two different environments that may be backend-frontend or backend-backend, can "effectively" communicate.
So there is a clear separation of motivation behind both the concepts. Now, from your viewpoint, you may use a hybrid approach which might work, and it may also lead to interesting findings related to performance, architectural design or overheads as well.
Publishing directly from the client is possible, but the caveat is that it means that the client needs to have the proper credentials to publish. For this reason, it may be preferable to have the service do the publishing in response to requests sent from the clients.

a completely decoupled OO system?

To make an OO system as decoupled as possible, I'm thinking of the following approach:
1) we run an RMI/directory like service where objects can register and discover each other. They talk to this service through an interface
2) we run a messaging service to which objects can publish messages, and register subscription callbacks. Again, this happens through interfaces
3) when object A wants to invoke a method on object B, it discovers the target object's unique identity through #1 above, and publishes a message on the message service for object B
4) message services invokes B's callback to give it the message
5) B processes the request and sends the response for A on message service
6) A's callback is called and it gets the response.
I feel this system is as decoupled as practically possible, but it has the following problems:
1) communication is typically asynchronous
2) hence it's non real time
3) the system as a whole is less efficient.
Are there any other practical problems where this design obviously won't be applicable ? What are your thoughts on this design in general ?
Books
Enterprise Integration Patterns
It appears he's talking about using a Message Oriented Middleware
Here are some things to consider
Security
What will prevent another rogue service from registering as a key component in your system. You will need way to validate and verify that services are who they say they are. This can be done through a PKI system. There are scenarios that you might not need to do this, if your system is hosted entirely on your intranet. IF that is the case Social Engineering and Rogue Employees will be your biggest threat.
Contract
What kind of contract will your clients have with the services? Will messages all be serialized as XML and sent as a TextMessage? If you use a pure byte message you'll have to be careful about byte order if your services are to run on multiple platforms.
Synchronization
Most developers are not able to comprehend and utilize asynchronous messages correctly. Where possible it might be in the best interest of your design to create a way to invoke "synchronous" messages. I've done this in the past by creating a sendMessageAndWait() method with a timeout and a return object. Within the method you can create a temporary topic id to receive the response, register a listener for it, then use locks to wait for a message to be returned on your temporary topic.
Unsolicited Messages
What happens if you want to allow your service(s) to send unsolicited messages to your clients? A critical event happened in Service A and it must notify your clients or possibly a Watch Dog service. Allow for your design to register for a common communication channel for services to communicate with clients without clients initiating the conversation.
Failover
What happens if a critical service processing your credit cards goes down? You'll need to implement a Failover and Watch Dog service to ensure that your key infrastructure is always up and running. You could register a list of services within your registry then your register could give out the primary service, falling back to a secondary service if your primary stops communicating. Or if your Message Oriented Middleware can handle Round Robin messaging you might be able to register all the services on the same topic. Think about creating a way to know when a service has died. Since most messages are Asynchronous it will be difficult to determine when a service has gone offline. This can be done with a Heartbeat and Watch Dog.
I've created this type of system a few times in my past for large systems that needed to communicate. If you and other developers understand the pros and cons of such a system it can be very powerful and flexible.
The biggest piece of advice I can give is to build a toolkit for your other developers so they don't have to think about how to register a service, or implement failover, or respond to messages from a client. These are the sorts of things that will kill your system and have others say it is too complicated. Making it painless for them will allow your system to work the way you need it with flexibility and decoupling while not burdening your developers with understanding enterprise design patterns.
This is not a Ivory Tower Architect/Architecture. It would be if he said, "This is how it will do done, now go do it and don't bother me about it because I know I'm right." If you really wanted to reference a Anti-Pattern it could be Kitchen Sink, maybe. Nah now that I think about it, it isn't Kitchen Sink either.
If you can find one please post it as a comment.
Anti-Patterns
Coupling is simply a balance between efficiency and re-usability. If you wish the modules of your system to be as reusable as possible then that will undoubtedly come at a cost.
Personally I think it best to define some key assumptions which may tighten coupling, but bring increased efficiency.
There are design patterns which never see the light of day just because the benefit they provide is not worth the cost in complexity.
What's the simplest thing that could possibly work? Do modularize into reasonable size routines, but avoid interfaces, services, messages and all of this unless you are going to have multiple implementations or multiple hardware resources to divide a job.
Make it simple, then refactor those parts that turned out to matter.