I'm building a backend using RabbitMQ and Spring. My POST, UPDATE and DELETE endpoints works fine using my message broker (rabbitMQ).
However, I dont know how should I implement a GET endpoint using message broker. Is there any way for retrieving a database info for frontend using asynchronous communication?
Edit.: i have found the solution. You should clone the data from microservice X if you want to use it at microservice Y. Also, you have to keep this data updated sending it to Y everytime if change it at X.
Microsoft have some good stuff about microservices and it helped me a lot: https://learn.microsoft.com/pt-br/dotnet/architecture/microservices/architect-microservice-container-applications/communication-in-microservice-architecture
The problem here is that you are using a request-response protocol (http) that implies synchronous communication with a asynchronous backend technology.
The problem is the following: with http you are using a thread of the server thread pool to execute the request and return the response but because you are using a message broker the thread that handles the request is not the same as the thread that recieve the response.
There are two possible solutions, if you want to continue using asynchronous communication to handle the queries (GETs) you have to use some protocol that not use a request-response model like SSE or WebSocket. Spring could handle SSe natively returning a Flux or Mono in your controller.
Other option is to make it synchronous and make a query call to database to get the result blocking the thread until you get the data
Related
We are in the process of designing the migration of our monolithic Java application to microservices to meet various client requirements such as scalability, high availability, etc. The core function of our application is data processing, i.e. retrieve data from a source, put it through 0 or more transformations, and finally push the result to a destination. For this reason, we are looking at Spring Cloud Data Flow running on Kubernetes and Kafka to do the heavy lifting for us, with a few custom built stream applications to handle our business logic.
One thing we have not yet figured out though is how it could handle synchronous responses to requests being sent in via an HTTP source - specifically when some processing is required before responding. For example, let us say that a request is received containing two different amounts in a JSON packet. We then pass this on to a custom "addition" transformer that outputs the sum of these amounts, and needs to return the result back to the calling party. However, because the transformer is a completely separate process that received the data by consuming it from a Kafka topic, it has no access to the original HTTP connection to respond.
Is this something that is possible with Spring Cloud Data Flow, perhaps by combining it with something like Spring Cloud Gateway to manage the HTTP connection? Or are we barking up the wrong tree completely?
It is not easy combine Async Flows (Spring Cloud Data Flow) with a Sync HTTP Flow (HTTP Requests have a timeout and Async Flow processing time is not known upfront). What you can do is return an id as response for your HTTP source and have another HTTP Endpoint to check the status of the initial request and get the result back using that. This is a polling approach.
I use Angular with Spring for internal API communication. Now I need to call external api to get some data. That external API provides callback feature, so I trigger call from Angular, call Spring rest method which, at the end, calls external API.
On the other hand I get data on my callback methods (Spring rest also), but I dont know how to transfer those data back to Angular.
Is websocket the only option?
If internal API calls are longer than the allowable client timeout, then you will need to find a WebSocket or WebSocket-like alternative. The alternative to WebSockets is to use long-polling (good example with source code here), which is essentially having the client repeatedly make requests until the original task is completed and the data can be sent. Either way, you'll need to use a pub/sub mechanism of some sort to handle multiple users, which is where things can get complicated.
Pub/sub can be complicated and I don't have an example on-hand, but essentially you must (1) have the client subscribe to a channel using a unique identifier (you can do this with CometD via a service channel), (2) evaluate the response, (3) publish the response to the client's subscribed channel, and finally (4) close the channel when it's no longer in use.
I've had some luck with CometD as a library to simplify pub/sub channel management, and it provides a good abstraction for asynchronous communication, although I haven't tried it with Spring and it might be heavy for what you want to do.
Another option that I'm less familiar with is to use Spring with STOMP. This seems to come recommended by others. Spring does provide ways to send messages to single users using STOMP: Sending message to specific user on Spring Websocket
I'd recommend following the above STOMP example.
Additional STOMP resources:
Getting Started with WebSockets (Spring)
Enable STOMP Over WebSocket
Angular2 with Stomp.js
As a side note, throttling may be necessary here, too, as with any time that you can spawn long-running threads from clients.
If you choose not to use STOMP or CometD, then a lighter solution could be to roll your own pub/sub for this single case using Spring's DeferredResult (as in Roger Hughes example), tying the subscription request to the long-poll request via a UUID token, which might also be the session ID if you choose to disallow concurrent requests per user. On subscription, the system can associate the request with a UUID and return this UUID to the client. The client can then make long-poll requests (again, as in Roger Hughes example) but with the UUID attached. The server can wait until the request for the given UUID has completed and then return the result to the client via the client's active long-poll request.
Channel management (i.e., request/UUID-tracking) can be done by clearing the channel on DeferredResult result retrieval and removing orphan channels with a separate thread acting as a GC -- or, perhaps better yet, automatically clearing orphan channels by removing them on DeferredResult completion/timeout if no active listeners exist. If you opt for the latter option, you will want to make sure that the client won't have any delay between its long-poll requests so that the DeferredResult doesn't unintentionally complete with no listeners.
I am working on a project which have many legacy heterogeneous systems. We are planing to connect them using JMS/MOM/ESB but need Synchronous web service calls from client.
i.e Request/Response architecture using web service is a requirement.
Client will make calls and wait for response.
My question is how can we implement Request/ response system which internally work on JMS/MOM to connect desperate systems?
Second question : Do any existing JMS/MOM or ESB implementations support such synchronous architecture?
first about second question: All of them support such architecture.
second about first:-)
just a brief idea:
when you send a message to target JMS Queue you have to have a unique message ID (in headers as example) then target system must answer (response) to "replyTo" queue. Then you have to have listener on that replyTo queue with filter by that unique ID and your flow must wait for response from that listener.
Something like that...
I want to deploy a scalable set of microservices. Every service should communicate via REST to each other. Also I need to request third-party services which will be slow and unstable.
So I came up with the idea to make it event-driven and use apache kafka.
Something like:
WebClient_X--request--->LoadBalancer--forward-->A-Service_1--request--->ThirdPartyService
A_Service_1 needs to poll the ThirdPartyService for the results and writes them into kafka.
A_Service_1--->Kafka
Now what?
How is it possible to send the results stored in the kafka topic back to the requesting WebClient_X.
Remember:
- A-Service is deployed N-times behind the LB.
- the A-Service_1 instance returned a Response.created(uuid) to the WebClient
On solution would be to make the WebClient consume the kafka topic. But this seems to be a stupid idea.
After think about it a lot I came up with the following idea :
all instances of a_service consume the Kafka topic equaly (no balancing)
the results are stored in a cache (local)
the webclient needs to poll for the result with the UUID.
In the Future I will replace the cache with a redis cluster or a clustered memcache.
An alternativ to polling would be websockets. But this seems to have some downsizes.
I'm looking for a way of implementing a simple API to receive log messages (for various events across various systems).
We've concluded an HTTP get request is the most open (lowest barrier to entry) for the different code bases and systems that would need to post to this server.
The server itself needs to provide an HTTP GET api where I would send a message e.g. logging.internal/?system=email&message=An email failed
However we'd like this to be non blocking so any application can throw information to this server and never have to wait (not slowing any production systems).
Does anyone know of any framework to implement this in Java, or an appropriate approach?
In java, for the server, you can use any implementation of JAX-RS for the Restful part, and when processing the message, just call an asynchronous EJB method ( http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html ), which will do the longer processing.
This will allow the RESTful request to return as fast as possible.
In this case, the only blocking part will be the http request/response.
If you want to make it less blocking, issue the RESTful request from the client in an Async method as well (or a Message Driven Bean if using Java EE 5).