We are looking to develop a number of services, but are not sure which "response" mechanism is the best route to go. The two contenders are:
HTTP callbacks, where the service would update the client application via "pinging" it with update messages sent via HTTP requests
Message Passing, where the service would update the client via publishing messages into a pub-sub queue on a message server
In both cases, both the caller and the services are within our network, we have full control over them, and things we develop are the only users of the services.
What are the pros / cons of each way of providing status updates to the calling application, and what, if any, pros / cons would there be for making the initial request via one method or the other?
Note: The first service we have in mind for this is an email service similar to SendGrid, which we can't use for various reasons, but still need the same functionality.
The main difference would be the quality of service that you get "out of the box" with a messaging server.
If you go with HTTP then your application has to take care of what happens when a message doesn't arrive as expected. To get an idea of the issues you need to consider and the complexities involved in solving them, take a look at WS-ReliableMessaging or HTTPLR.
With messaging, you get a configurable level of reliability out of the box. And there's a lot of good choice these days such as ActiveMQ, RabbitMQ, 0MQ.
My personal preference is for reliability to be handled at the transport layer (by messaging), but then for a good discussion and dissenting view, check out "Nobody Needs Reliable Messaging."
Related
I'm designing a system that uses a microservices architecture with event-based communication (using Google Cloud Pub/Sub).
Each of the services is listening and publishing messages so between the services everything is excellent.
On top of that, I want to provide a REST API that users can use without breaking the event-based approach. However, if I have an endpoint that triggers event X, how will I send the response to the user? Does it make sense to create a subscriber for a "ProcessXComplete" event and than return 200 OK?
For example:
I have the following microservices:
Service A
Service B
Frontend Service - REST Endpoints
I'm want to send this request "POST /posts" - this request sent to the frontend service.
The frontend service should trigger "NewPostEvent."
Both Service A and Service B will listen to this event and do something.
So far, so good, but here is where things are starting to get messy for me.
Now I want to return the user that made the request a valid response that the operation completed.
How can I know that all services finished their tasks, and how to create the handler to return this response?
Does it even make sense to go this way or is there a better design to implement both event-based communications between services and providing a REST API
What you're describing is absolutely one of the challenges of event-based programming and how eventual-consistency (and lack of atomicity) coordinates with essentially synchronous UI/UX.
It generally does make sense to have an EventXComplete event. Our microservices publish events on completion of anything that could potentially fail. So, there are lots of ServiceA.EventXSuccess events flowing through the queues. I'm not familiar with Google Cloud PubSub specifically, but in general in Messaging systems there is little extra cost to publishing messages with few (or no) subscribers to require compute power. So, we tend to over-articulate service status by default; it's easy to come back later and tone down messaging as needed. In fact, some of our newer services have Messaging Verbosity configurable via an Admin API.
The Frontend Service (which here is probably considered a Gateway Service or Facade Layer) has taken on the responsibility of being a responsive backing for your UI, so it needs to, in fact, BE responsive. In this example, I'd expect it to persist the User's POST request, return a 200 response and then update its local copy of the request based on events it's subscribed to from ServiceA and ServiceB. It also needs to provide a mechanism (events, email, webhook, gRPC, etc.) to communicate from the Frontend Service back to any UI if failure happens (maybe even if success happens). Which communication you use depends on how important and time-sensitive the notification is. A good example of this is getting an email from Amazon saying billing has failed on an Order you placed. They let you know via email within a few minutes, but they don't make you wait for the ExecuteOrderBilling message to get processed in the UI.
Connecting Microservices to the UI has been one of the most challenging aspects of our particular journey; avoiding tight coupling of models/data structures, UI workflows that are independent of microservice process flows, and perhaps the toughest one for us: authorization. These are the hidden dark-sides of this distributed architecture pattern, but they too can be overcome. Some experimentation with your particular system is likely required.
It really depends on your business case. If the REST svc is dropping message in message queue , then after dropping the message we simply return the reference ID that client can poll to check the progress.
E.g. flight search where your system has to calls 100s of backend services to show you flight deals . Search api will drop the message in the queue and save the same in the database with some reference ID and you return same id to client. Once worker are done with the message they will update the reference in DB with results and meanwhile your client will be polling (or web sockets preferably) to update the UI with results.
The idea is you can't block the request and keep everything async , this will make system scaleable.
I am dealing with communication between microservices.
For example (fictive example, just for the illustration):
Microservice A - Store Users (getUser, etc.)
Microservice B - Store Orders (createOrder, etc.)
Now if I want to add new Order from the Client app, I need to know user address. So the request would be like this:
Client -> Microservice B (createOrder for userId 5) -> Microservice A (getUser with id 5)
The microservice B will create order with details (address) from the User Microservice.
PROBLEM TO SOLVE: How effectively deal with communication between microservice A and microservice B, as we have to wait until the response come back?
OPTIONS:
Use RestAPI,
Use AMQP, like RabbitMQ and deal with this issue via RPC. (https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html)
I don't know what will be better for the performance. Is call faster via RabbitMQ, or RestAPI? What is the best solution for microservice architecture?
In your case using direct REST calls should be fine.
Option 1 Use Rest API :
When you need synchronous communication. For example, your case. This option is suitable.
Option 2 Use AMQP :
When you need asynchronous communication. For example when your order service creates order you may want to notify product service to reduce the product quantity. Or you may want to nofity user service that order for user is successfully placed.
I highly recommend having a look at http://microservices.io/patterns/index.html
It all depends on your service's communication behaviour to choose between REST APIs and Event-Based design Or Both.
What you do is based on your requirement you can choose REST APIs where you see synchronous behaviour between services
and go with Event based design where you find services needs asynchronous behaviour, there is no harm combining both also.
Ideally for inter-process communication protocol it is better to go with messaging and for client-service REST APIs are best fitted.
Check the Communication style in microservices.io
REST based Architecture
Advantage
Request/Response is easy and best fitted when you need synchronous environments.
Simpler system since there in no intermediate broker
Promotes orchestration i.e Service can take action based on response of other service.
Drawback
Services needs to discover locations of service instances.
One to one Mapping between services.
Rest used HTTP which is general purpose protocol built on top of TCP/IP which adds enormous amount of overhead when using it to pass messages.
Event Driven Architecture
Advantage
Event-driven architectures are appealing to API developers because they function very well in asynchronous environments.
Loose coupling since it decouples services as on a event of once service multiple services can take action based on application requirement. it is easy to plug-in any new consumer to producer.
Improved availability since the message broker buffers messages until the consumer is able to process them.
Drawback
Additional complexity of message broker, which must be highly available
Debugging an event request is not that easy.
Personally I am not a fan of using a message broker for RPC. It adds unnecessary complexity and overhead.
How do you host your long-lived RabbitMQ consumer in your Users web service? If you make it some static singleton, in your web service how do you deal with scaling and concurrency? Or do you make it a stand-alone daemon process? Now you have two User applications instead of one. What happens if your Users consumer slows down, by the time it consumes the request message the Orders service context might have timed-out and sent another message or given up.
For RPC I would suggest simple HTTP.
There is a pattern involving a message broker that can avoid the need for a synchronous network call. The pattern is for services to consume events from other services and store that data locally in their own database. Then when the time comes when the Orders service needs a user record it can access it from its own database.
In your case, your Users app doesn't need to know anything about orders, but your Orders app needs to know some details about your users. So every time a user is added, modified, removed etc, the Users service emits an event (UserCreated, UserModified, UserRemoved). The Orders service can subscribe to those events and store only the data it needs, such as the user address.
The benefit is that is that at request time, your Orders service has one less synchronous dependency on another service. Testing the service is easier as you have fewer request time dependencies. There are also drawbacks however such as some latency between user record changes occuring and being received by the Orders app. Something to consider.
UPDATE
If you do go with RabbitMQ for RPC then remember to make use of the message TTL feature. If the client will timeout, then set the message expiration to that period. This will help avoid wasted work on the part of the consumer and avoid a queue getting backed up under load. One issue with RPC over a message broker is that once a queue fills up it can add long latencies that take a while to recover from. Setting your message expiration to your client timeout helps avoid that.
Regarding RabbitMQ for RPC. Normally we use a message broker for decoupling and durability. Seeing as RPC is a synchronous communication, that is, we are waiting for a response, then durability is not a consideration. That leaves us decoupling. The question is does that decoupling buy you anything over the decoupling you can do with HTTP via a gateway or Docker service names?
I have a system that exposes a REST API with a rich set of CRUD endpoints to manage different resources.
The REST API is used also by a front-end application that executes calls by using Ajax.
I would like to make some of these calls asynchronous and add reliability.
The obvious choice seems a message broker (ActiveMQ, RabbitMQ, etc...).
Never used message brokers before and I am wondering if they can be "put in front of" the REST API without having to rewrite them.
I do not want to access the REST API only through the messaging system: for some endpoints, a call must always be synchronous and the reliability is less important (mainly because in case of error the user receives an immediate feedback).
Would a full ESB be a better option for this use case?
If I understand your question, you would like to "register" an API endpoint as a subscriber so that it could receive the messages sent to a given queue.
I do not think that a message broker can be configured to do this.
For example, if you want to use a message broker, both your producers and subscribers need to use the JMS API.
I do not know if a solution can be to implement a subscriber that will execute the corresponding API call. In this case, the reliability is compromised because the message will be dequeued before the API call is executed. It can make sense if the subscriber is running in the same process of the API, but in this case it is not clear why you should use a REST API instead of a library.
IMO #EligioEleuterioFontana you have a misunderstanding of the roles of:
an RESTful Api
a message broker
These are two different subsystems which provide different services.
Now, let's explain their roles with respect to your requirements:
You have clients (desktop browsers, mobile phone browsers or apps) which need to get/push data to your system. (Assumption from the REST API mention).
Requests from the clients are using HTTP/HTTPS (that's the REST API part of your requirement).
Any data that is pushed, you wish to make this more responsive, quicker, reliable.
If I've gotten that right, then I would answer it as:
All clients need to push requests to a REST API because this does just more than simple CRUD. The Api also handles things like security (authentication and authorization), caching, possibly even request throttling, etc.
REST API should always been the front end to clients as this also 'hides' the subsystems that the API uses. Users should never see/know about any of your subsystem choices (eg. what DB you are using. Are you caching? if so, with what? etc).
Message Brokers are great for offloading the work that was requested now and handling the work later. There's heaps of ways this can be done (queues or pub/sub, etc) but the point here is this is a decision the clients should never see or know about.
MB's are also great for resilience (as you noted). If something fails, the message on a queue would be re-attempted after 'x' time ... etc. (no, I'm not going to mention poison queues, dead letter queue, etc).
You can have some endpoints of the Api that are synchronous. Sure! Then have others that leverage some eventual consistency (i.e. for that request, I'll deal with it later (even if later in 5 secs later) and just return the response to the client saying "thanks! got it! I'll do it soon"). This is the asynchronous workflow you are after.
The API endpoints needs to be simple, concise and hopefully pretty stable. What you do behind the scenes as you change things hopefully will be hidden away from the clients. This includes the use of message brokers.
Anyway, that my take on how I see REST APIs and Message Brokers and how they related to each other.
It might be worth looking into the Google Cloud sub/pub? -
https://cloud.google.com/pubsub/docs/overview
I heard Amazon uses HTTP for its microservice based architecture. An alternative is to use a messaging system like RabbitMQ or Solace systems. I personally have experience with Solace based microservice architecture, but never with REST.
Any idea what do various big league implementations like Amazon, Netflix, UK Gov etc use?
Other aspect is, in microservices, following things are required (besides others):
* Pattern matching
* Async messaging.. receiving system may be down
* Publish subscribe
* Cache load event.. i.e. on start up, a service may need to load all data from a couple of other services, and should be notified when data is completely loaded, so that it can 'know' that it is now ready to service requests
These aspects are naturally done with messaging rather than REST. Why should anyone use REST (except for public API). Thanks.
A standard that I've followed in the past is to use web services when the key requirement is speed (and data loss isn't critical) and messaging when the key requirement is reliability. Like you've said, if the receiving system is down, a message will sit on a queue until the system comes back up to process it. If it's a REST endpoint and it's down, requests will simply fail.
REST API presumes use of HTTP only. it is quite stone age technology and does not accept async. messaging. To plugin messaging there, I would consider WebSockets Gateways
-sorry for eventually dummy statements
I am currently struggling with a design issue involving REST. The application I am designing has a requirement to send out events and also support pub/sub style of interaction. I am unable to come up with a design to provide these interaction style without breaking the REST’s “Stateless interaction” constraint. I am not against polling as some people seem to be (polling sucks) , but my application demands a event based and pub/sub style of interaction (polling is not an option for me). So, my question is:
Can I design a RESTful application that supports event based and pub/sub interactions without breaking the REST contraint?
Is REST style suitable for this kind of interaction style?
I'd recommend the Distributed Observer Pattern by Duncan Cragg as a good read (bit difficult to grok but worth the effort).
As others have indicated its likely you'll need to use polling but as you rightly say subscribers could register their own interest (POST to create subscription). If you view the subscription as its own resource, a contract between the publisher and subscriber, then I wouldn't view it as a breaking REST constraints (see State and Statelessness at page 217 of RESTful Web Services for the difference between application and resource state)
I assume you mean the server should notify the clients about events. I don't see how the specific technology matters here: you will face the same problems, and have to pick a solution from the same pool, regardless of using REST, SOAP-based web services, or any other alternative.
The basic question is, can your server initiate connections? Complementing this, can the clients listen to a port? If so, the client registers (sub), and the server notifies of events (pub). Both the registration operation and the notification events can be RESTful.
You need both server-initiated connections and listening clients. If either is not an option (e.g., because the client is a web browser), you will have to make do with polling (you can also look into something like websockets, if you're dealing with a browser). Design your polling carefully: the server response to the polling event should indicate a minimum delay before the client may poll again. The initial implementation of the server can return a constant for this delay value, but later on (assuming the clients are well-behaved) this will allow you to control the load on the server, differentiate between critical and less-critical clients, and so on.
And of course, the polling can be RESTful.
I don't see a reason why RESTful interfaces should not support events.
It will have to be done through polling, mind you; and that would be true even if you were to use SOAP instead.
While your web servers should definitely remain stateless, you probably do have a DB somewhere on the back end. You can use this DB to handle subscriptions to events by adding a subscription table.
Webhooks are the answer to this problem. They allow events without violating the REST principles.
Just a fast check on the REST constraints:
client-server architecture
stateless
cache
uniform interface
identification of resource
manipulation of resource through representations
self-desriptive messages
hypermedia of the engine of application state
layered system
code on demand (optional)
From the Fielding dissertation:
The client-server style is the most frequently encountered of the
architectural styles for network-based applications. A server
component, offering a set of services, listens for requests upon those
services. A client component, desiring that a service be performed,
sends a request to the server via a connector. The server either
rejects or performs the request and sends a response back to the
client.
Btw. an event based system would probably violate most of the constraints. It is hard to define things like hypermedia the engine of application state without clients (since the other name of application state is client state) and hyperlinks (since they are meaningless by pub/sub), and so on...
Anyways it is an interesting question how to design an event based system somewhat similar to REST. I think you should publish self-descriptive messages containing RDF, but that's just a tip. Polling can be a viable solution, but if I were you I would not try to force REST on an event based system...
update 2016.05.15.
As far as I understand the client - server architecture - Fielding describes here and here in his dissertation - uses always REQ/REP communication. The client sends the request and the REST service responds. If you want to have something like PUB/SUB without the violation of the client - server constraint, the only way to do that is the usage of polling. If you don't want to use polling, then ofc. you can use a REST service and a websocket service together, it is not forbidden...