I am building an application which connect with other too. For the application I need to take a request from a websocket connection. Once i received the request need to send the request to some other application for processing and there will be few cases.
If second application return accepted then wait for a response from 3rd application (3 will send response to 2nd and 2nd will initiate a push model).
If second application return other than accepted then return false to the request
My confusion is, this way I will handle the request as synchronous or asynchronous ?
As in case #1 I have to wait for some time to receive response from another application. more over in case #2 I can immediately process a request.
Sequence diagram for clarity of flow
Related
Say you have an Application A and an Application B that communicates together using ActiveMQ queues. The communication happens as below.
A sends a request message to application B using the queue name
com.example.requestQueue
B consumes the message request from the queue name com.example.requestQueue
B takes some time to handle the message request and then sends a
response back to B using the response queue
name com.example.responseQueue
A consumes the response message from com.example.responseQueue queue and is done
If application B is always answering, there is no problem.
But if for some reason the application B consumes a message from the request queue com.example.requestQueue and never puts a response message in the response queue com.example.responseQueue, application A will wait forever.
Is there any way to solve this kind of problem please?
NB: The application A is written with Java and Camel and the application B is Written in C++
Thanks.
Camel supports request-reply flows in a single route (exchange pattern InOut), or you can break the request-reply into two separate routes (both exchange pattern InOnly) depending on your use case.
The request-reply patterns have timeout settings available based on the Camel component used. Add the timeout to the Application A Camel route request-reply.
ref: SJMS Component - Newer JMS component
ref: JMS Component - Original JMS component
ref: Request Reply pattern - Info on InOut patterns
Side note--
If Application A is also expected to return something to a caller (ie a web app or a REST/SOAP client), than you would want to make sure you set the messaging response timeout to be lower than than the timeout used by the caller. This allows Application A to return a proper exception/error to the caller before the caller's timeout occurs.
A client sends a request and catches a timeout exception. However the server is still processing the request and saving it to the database. Before that happening, the client already sent a second request which doubles the record on the database. How do I prevent that from happening? Im using java servlets and javascript.
A few suggestions:-
1) Increase the client timeout.
2) Make the server more efficient so it can respond faster.
3) Get the server to respond with an intermediate "I'm working on it" response before returning with the main response.
4) Does the server need to do all the work before it responds to the client, or can some be offloaded to a seperate process for running later?
A client sends a request and catches a timeout exception. However the server is still processing the request
Make the servlet generate some output (can be just blank spaces) and flush the stream every so often (every 15 seconds for example).
If the connection has been closed on the client side, the write will fail with a socket exception.
Before that happening, the client already sent a second request which doubles the record on the database
Use the atomicity of the database, for example, a unique key. Start the process by creating a unique record (maybe in some "unfinished" status), it will fail if the record already exists.
i am trying to create a http client based on netty. I have written the code based on the HttpSnoopClient example given in Netty site. But the problem is HttpResponse are handled by HttpSnoopClientHandler & HttpRequests are sent in HttpSnoopClient & i want to sync it. as in if i send a request i want to make sure that i will send the next request once i know the response to the previous. But since both are handled in different class, It is becoming difficult to do the same.
One thing i did was to create a setResponse() method in HttpTarget & HttpSnoopClientHandler will be setting the HttpResponse when it receives the Response from the sever. But i don't think it is a good approach since i won't be able to know the reposne was for which request.
So basically i want to do it synchronously i.e. send a request(channel.writeandFlush(req)) in HttpSnoopClient then wait till the response is received by the HttpSnoopCLientHandler & once it recieves a HTTP 1.1 200 OK then send the next request.
Can anyone tell me a good approach for doing it. Thanks in advance!
I had a similar use case where I had to block concurrent requests till one completes for a resource. I implemented a ConcurrentHashMap<RequestKey, ArrayList<ChannelHandlerContext>>> which will hold all the concurrent requests ChannelHandlerContext (ctx) and on completion of the first request raise an event which would trigger all other ctx to consume the cached response. In all this I had to make sure the AUTO_READ was set to false for fine grain control over the reads on each channel.
channelRead ->
if(map.contains(reqKey)){
map.add(reqKey, list.add(ctx))
//do nothing with AUTO_READ = false and do not initiate any ctx.* methods
}else{
//firstRequest
map.add(reqKey, new ArrayList<CTX>(){{ add(ctx);}})
//continue with request execution
//cache response and raise event on completion
}
userEventTriggered ->
onCompletionEvent {
ctxList = map.get(reqKey).clone();
map.remove(reqKey);
for(blockedCtx : ctxList){
//respond back with cached response to each blockedCtx
}
}
#norman-maurer would you give your take on this !!!
As you're creating a new HttpSnoopClientHandler for each connection, I would consider turning HttpSnoopClientHandler into a ChannelDuplexHandler. In the write method you can store a reference to the outgoing http request. When the response is received you can call your setResponse method with (channel, request, response). This should provide enough context so you can process the response correctly.
If your client is pure request/response, does not issue unrelated requests separately, and you want your application thread to process responses sequentially, then you could use a SynchronousQueue to coordinate responses with allowing the main thread to continue. Alternatively your callback can process the responses internally.
You can also extends this technique to use HTTP pipelining. HTTP pipelining guarantees that responses are returned in the order that requests are issued. In HttpSnoopClientHandler you maintain a queue of requests. As each response is returned you match it to the request at the front of the queue.
Assuming no keep alives, when a servlet container is acting as a stand alone server, I assume that the servlet's thread is not released until the entire response is sent to the client (say a web browser). Is this a correct assumption?
But what happens if the servlet is behind a reverse proxy like Nginx? Is the thread released once the response is delivered to Nginx, or is it held until the response is sent to its final client (say a browser)?
Update: Let me try make this a bit more clear.
It takes mere milliseconds (say 2ms) for a response to be sent from servlet to proxy like nginx. But it can then take an additional 80ms (or so) for the final response to be sent from nginx to the browser. Does the servlet release the thread/stream once the response is sent to nginx, or does the servlet hold onto them until the response is sent to the browser (that is the entire 80ms)
Question: I assume that the servlet's thread is not released until the entire response is sent to the client (say a web browser). Is this a correct assumption?
Ans: No it is wrong. Servlet container will just write the content to the socket and return. It is not guaranteed that return from write() method will ensure that the response has reached the client.
Question: Is the thread released once the response is delivered to Nginx, or is it held until the response is sent to its final client (say a browser)?
Ans: When Nginx is behind , then the client for Servlet container is Nginx. It is not aware of actual remote client. So, the thread will be released once the response is written to Nginx.
The server container not being able to send a response to the client will trigger an exception that will be handled by the container. You can enclose the writing to the outputstream or writer by a try catch finally (with close()) but you don't need to, the container will manage, including the return of the thread to the pool.
Regards
S
A servlet does not see the network. According to the specifications It is handled 2 objects: a Request and a Response to be filled in (in the case of HTTP, this means a HTTPRequest and a HTTPResponse). It shall process the request data within the request object, and write to the buffer in the response object. Once that content is commited by the servlet, the container may do some postprocessing (using filters) and will transmit it back to the client.
The servlet thread returns naturally to the pool once the call to the request handling method finishes (that may happen after the payload is sent back to the client, if the method has to do further work.
Note that because the servlet doesn't see the network and is only concerned about a single request, the state of the http connection (keep-alive or close) is independent of the servlet lifetime; several servlets may handle the different requests pipelined in a single connection. See this question for a related issue.
I'm having trouble establishing AsyncContexts for users and using them to push notifications to them. On page load I have some jQuery code to send the request:
$.post("TestServlet",{
action: "registerAsynchronousContext"
},function(data, textStatus, jqXHR){
alert("Server received async request"); //Placed here for debugging
}, "json");
And in "TestServlet" I have this code in the doPost method:
HttpSession userSession = request.getSession();
String userIDString = userSession.getAttribute("id").toString();
String paramAction = request.getParameter("action");
if(paramAction.equals("registerAsynchronousContext"))
{
AsyncContext userAsyncContext = request.startAsync();
HashMap<String, AsyncContext> userAsynchronousContextHashMap = (HashMap<String, AsyncContext>)getServletContext().getAttribute("userAsynchronousContextHashMap");
userAsynchronousContextHashMap.put(userIDString, userAsyncContext);
getServletContext().setAttribute("userAsynchronousContextHashMap", userAsynchronousContextHashMap);
System.out.println("Put asynchronous request in global map");
}
//userAsynchronousContextHashMap is created by a ContextListener on the start of the web-app
However, according to Opera Dragonfly (a debugging tool like Firebug), it appears that the server sends an HTTP 500 response about 30000ms after the request is sent.
Any responses created with userAsyncContext.getResponse().getWriter().print(SOME_JSON) and sent before the HTTP 500 response is not received by the browser, and I don't know why. Using the regular response object to send a response (response.print(SOME_JSON)) is received by the browser ONLY if all the code in the "if" statement dealing with AsyncContext is not present.
Can someone help me out? I have a feeling this is due to my misunderstanding of how the asynchronous API works. I thought that I would be able to store these AsyncContexts in a global map, then retrieve them and use their response objects to push things to the clients. However, it doesn't seem as if the AsyncContexts can write back to the clients.
Any help would be appreaciated.
I solved the issue. It seems as though there were several problems wrong with my approach:
In Glassfish, AsyncContext objects all have a default timeout period of 30,000 milliseconds (.5 minutes). Once this period expires, the entire response is committed back to the client, meaning you won't be able to use it again.
If you're implementing long-polling this might not be much of an issue (since you'll end up sending another request after the response anyway), but if you wish to implement streaming (sending data to back to the client without committing the response) you'll want to either increase the timeout, or get rid of it all together.
This can be accomplished with an AsyncContext's .setTimeout() method. Do note that while the spec states: "A timeout value of zero or less indicates no timeout.", Glassfish (at this time) seems to interpret 0 as being "immediate response required", and any negative number as "no timeout".
If you're implementing streaming , you must use the printwriter's .flush() method to push the data to the client after you're done using its .print() .println() or .write() methods to write the data.
On the client side, if you've streamed the data, it will trigger a readyState of 3 ("interactive", which means that the browser is in the process of receiving a response). If you are using jQuery, there is no easy way to handle readyStates of 3, so you're going to have to revert to regular Javascript in order to both send the request and handle the response if you're implementing streaming.
I have noticed that in Glassfish if you use AsyncContext and use .setTimeOut() to a negative number the connection is broken anyway, to fix this I had to go to my Glassfish admin web configurator : asadmin set
configs.config.server-config.network-config.protocols.protocol.http-listener-1.http. And set timeout to -1. All this to avoid glassfish finish the connections after 30 sec.