Why do multiple RPC calls in GWT significantly slow response time? - java

I'm testing a Google Web Toolkit application and having some performance issue with multiple RPC calls. The structure of the app is:
User submits a query
Initial query is serviced by a single server-side servlet
Once initial reply received, multiple components are subsequently updated by iterating over each component and calling an update method, passing it the results of the initial query
Each component's update method does some work on the data passed to it, in addition to potentially calling other server-side services
On success of these calls, the component is updated in the UI.
With the initial query service and 1 component (effectively running sequentially), response time is fast. However, adding any other components (e.g initial query service + 2 components, these 2 components calling asynchronously) hugely impacts the response time.
Is there any way to improve / rectify this?
Example: (IQS = initial query, C1 = component 1, C2 = component 2, C1S = comp. 1 service, C2S = component 2 service)
Initial Query + 1 component
IQS, returned - propagating results, 1297273015477
C1, Sending server request,1297273015477
C1S, Sending back..., 1297273016486
C1, Receiving Complete, 1297273016522 (total time from initial call - 1045ms)
Initial Query + 2 components
IQS, returned - propagating results, 1297272667185
C1, Sending server request,1297272667185
C2, Sending server request,1297272668132
C1S, Sending back..., 1297272668723
C2S, Sending back..., 1297272669371
C1, Back at client to process, 1297272671077 (total time from initial call - 3892ms)
C2, Back at client to process, 1297272674518 (total time from initial call - 6386ms)
Thanks in advance.
Paul

I think you need to make your analysis more fine grained: in the data provided you have established that the client started the 2nd component call and got a response back 6386ms later. Some of this was
Going over the wire
Being received at the server
Processed at the server (this could be broken down, as well).
Sent back over the wire.
The GWT-RPC service really only has to do with 1 and 4. Do you know how long each step takes?

Well, I think your problem is not directly related to GWT. Because , I have used multiple rpc calls at same time, my application performance did not degraded.I think that you may have server side synchronization issues.

The overhead of http with cookies, and the sequencing of some of these (rather than firing all the request when the user is switching to another part of the application) is part of the reason why they seem to slow things down. E.G. A user requests a page, once that page's widgets are in place they fire requests for the data they're supposed to show, possibly making decisions to add more widgets based on that data (but hopefully passing the data into those widgets).
You might be looking for some tools that help you to create batched rpc calls like: gwt-dispatch. I don't think there's anything automatic.

A low-tech way to get more information is to put basic timing logging into every RPC to see how long they take. Create a new Date() at the top, subtract its ms from a new Date()'s ms at the end, print it to stdout or use Log.info() or whatever.
For something more industrial strength I used the "SpringSource tc" combined with Chrome's Speed Tracer in order to get a full stack view of what calls were taking what amount of time, and what was actually able to happen in parallel. Not trivial to set up but once I did I was able to zero in on the real issues (in my case it was getting tons of unnecessary information from Hibernate queries) very quickly.
Here's the basic info we used:
Download the tc Server Developer Edition (free)
http://www.springsource.com/products/tc-server-developer-edition-preview
NOTE: Do not even THINK about installing in a directory structure that has spaces.....
Installing tc Server: Main Steps
http://static.springsource.com/projects/tc-server/2.1/getting-started/html/ch06s02.html#install-developer-edition
Viewing Spring Insight Data In Google Speed Tracer
http://static.springsource.com/projects/tc-server/2.0/devedition/html/ch04s04.html
url is now localhost:8080 instead of the old port address for the other installation of tomcat.
One more detail, you'll need to make a .war file and deploy that to the tomcat directory. (You're not getting perf data on dev mode, but rather a local GWT compiled release)
-- Andrew # learnvc.com

Related

Request atomicity within microservices bounded context

Our project consists of multiple microservices. These microservices form a boundary to which the entry point is not strictly defined meaning each of microservices can be requested and can request other services.
The situation we need to handle in this bounded microservice context is following:
client (other application) makes the request to perform some logic and change the data (PATCH),
request times out,
while request is being processed client fires the same request to repeat the operation,
operation successfully completes,
second request is being processed the same way and completes within it's time and client gets response.
Now what happened is that the same was processed two times because of first timeout.
We need to make sure the same request won't get processed and application will respond with former response and status code.
The subsequent request is identified by the same uuid.
Now, I understand it's the client that should do requesting more precisely or we should have a single request entry point in out micorservices bounded context, but in enterprise projects the team doesn't own the whole system therefore we are a bit constrained with the solutions we propose for the problem. with this in mind while trying to not reinvent the wheel this comes to my mind:
The microservices should utilize some kind of session sharing (spring-session?) with the ability to look up the request by it's id before it gets processed and in described case, when first is being processed and second arrives, wait for the completion of the 1st and respond to the second with data of the first that has timed out for a client.
What I am struggling with is imagining handling the asynchronicity of replying to the second one and how to listen for session state of the first request.
If spring-session would be used (for example with hazelcast) I'm lacking some kind of concrete session state handler which would get fired when request ends. Is there something like this to listen for?
No code written yet. It's an architectural thought experiment that I want to discuss.
If unsure of understanding, read second time please, then I'm happy to expand.
EDIT: first idea:
process would be as follows (with numbering on the image):
(1) first request fired
(3) processing started; (2) request timed out meanwhile;
(4) client repeats the same request; program knows it has received the same request before because it knows the req. id.
program checks the cache and the state of that request id 'pending' so it WAITS (async).
computed result of first request is saved into the cache - orange square
(5) program responds to the first request with the data that was meant to be for the first one
idea is that result checking and responding to the repeated request would be done in the filter chain so it won't actually hit the controller when the second request is asynchronously waiting for the operation triggered by the first request to be done (I see hazelcast has some events when rows are added/updated/evicted from the cache - dunno if it's working yet) and when complete just respond (somehow write to the HttpServletResponse). result would be saved into the cache in postHandling filter.
Thanks for insights.
I'd consider this more of a caching paradigm. Stick your request/responses into an external cache provider (REDIS or similar), indexed by uuid. Having a TTL will allow your responses to automatically get cleaned up for requests that are never coming back, and the high-speed implementation (o1) should allow this to scale nicely. It will also out-of-the-box give you an asynchronous model (not a stated goal, but always a nice option).

How to limit the number of concurrent requests in web api?

How to limit by code the number of concurrent requests to web application, say to 3 requests ? Am I suppose to put each servlet class into a thread and create a global counter (by creating new class)?
How to limit by code the number of concurrent requests to web application, say to 3 requests ? Am I suppose to put each servlet class into a thread and create a global counter (by creating new class)?
You typically rely in the web container to limit the number of concurrent requests; e.g. by setting limit on the number of worker threads or connections ... in the web container configurations.
Apparently, if a Tomcat server gets more requests than it can handle, it will send generic 503 responses. For more information:
https://tomcat.apache.org/tomcat-8.5-doc/config/http.html - explains where / how the configs can be set
Tomcat responding HTTP 503 - gives an example of what would happen ...
But how can i display to the users that the wed reached its limit (like 3 requests)?
If you want to limit specific request types and display specific responses to the user, then you probably will need to implement this within each servlet, using a counter, etcetera.
But the problem with trying to do "nice" things when the server is overloaded is that doing the nice things tends to increase the load. This is particularly important:
when your server is grossly inadequate for the actual load from (real) users, or
when someone is DoS'ing you, either accidentally or deliberately.

Serving single HTTP request with multiple threads

Angular 4 application sends a list of records to a Java spring MVC application that has been deployed in Websphere 8 Servlet container. The list is then inserted into to a temp table. After the batch insert, a procedure call is made in order to do some calculations and return results. Depending on the size of the list that was inserted into temp table it may take anywhere between: 3000ms( N ~ 500 ), 6000ms( N ~ 1000 ), 50,000+ms ( N > 2000 ).
My asendach would be to create chunks of data and simultaneously send them to database for processing. After threads (Futures) return results I would aggregate them and return back to the client. To sum up, I would split a synchronous call into multiple asynchronous processes(simultaneously executed) and return back to the client over the same thread that initiated HTTP call - landed into my controller.
Everything would be fine and I would not be asking this questions if a more experienced colleague of mine was not strongly disagreeing with this approach. His reasoning is that using this approach is prone to exceptions due to thread interrupts / timeouts / semaphores and so on. Hi is going as far as saying that multithreading should be avoided within a web container because it can crash the Servlet container in case it runs out of threads.
He proposes that we should have the browser send multiple AJAX requests and aggregates/present data in chunks.
Can you please help me understand which approach is better and why?
I would say that your approach is much better.
Threads created by application logic aren't application container threads and limited only by operating system. While each AJAX request uses a thread from application container. So the second approach reduces throughput and increases the possibility of reaching application container limit while and the first one not. Performance also should be considered because it's much cheaper to create a thread than to send a request over network. Plus each network requests uses additional resources for authentication/authorization/encryption etc.
It's definetely harder to write correct multithread code and it can easily prone to errors. However it shouldn't stop you from doing it because concurrency can significantly increase your performance. It's pretty straightforward to handle interrupts and timeouts using Future and you for sure don't need semaphores here.
Exposing this logic to client looks like breaking of encapsulation. Imagine that you use rest api which forces you to send multiple request by splitting you data in chunks. What chunk size should i use? How to deal with timeouts/interrupts? How many requests should i sent? etc. You will have almost the same challenges in both approaches, but it's much easier to deal with them using specially designed for this libraries like ExecutorService and Future.

Akka: Is this the correct way to build REST web service with Actors?

What I am doing:
I am using play 2.5.7 (java) and trying to build a REST application.
When I get a call on my controller I ask the first actor, this actor can only solve part of the problem (getting additional data), which needs to be forwarded to another actor which uses the request data and additional data to update some more data, send an async void call (tell) to another actor and respond to the controller. All these (4) actors are #Injected in other actors or controller with Guice.
Flow of calls:
controller --(Patterns.ask)--> actor1 --(actor.forward)--> actor2 --(actor.forward)--> actor3 (-tell-> actor4) and --(sender().tell)--> controller.
Issue:
This works for first 4 calls. Then on actor1.forward keeps failing on every consecutive request; Patterns.ask times out. System.out on the line before actor1.forward works but not the actual forward. No matter the timeout value (tried even 20s). No change done in the request; I just hit the send button in postman every time.
I have two questions:
Why 4? Why does it fail after 4th request? Is it some config? What should I look for in config?
Is what I am doing with actors correct way to build a REST web service?
Update: I found the issue; it was caused due to consumption of Redis connections through the pool and never freeing them. But the second question I had still remains, is what I am doing here advisable?
Sure, this could be a reasonable design. But I would consider though whether it would be more maintainable to work with Future returning methods, unless your workflow requires some complex protocol between multiple moving pieces or internal state. It may also be worth considering Akka Streams, if your processing doesn't map well to async method calls.
Basically, actors are a pretty low-level tool. To the extent that you need them, I would try to minimize the surface area of your application where they are being directly used. Higher-level abstractions are better, where possible.

Tomcat Session Timeout while processing Request

I face a scenario where everything works fine with keeping session.setMaxInactiveInterval(15*60) //15 minutes
Now, there is one request in application where number of users are getting saved, which takes more then 15 minutes at server side as internally many operations are involved while saving each user.
When saveUser operation is performed from browser, request received at server, starts processing, after 15 minutes client see "Session Time out" but user saving operation still going on.
I want to avoid this scenario, and need is when request is received by server at that time till the time it responds back to client don't considered in-between time as inactive time.
I can very well do it by making setMaxInactiveInterval(-1) as first line of my method saveUser and just before giving response as setMaxInactiveInterval(15*60).
I am looking for standard approach or this is the standard approach to follow?
Is there any inbuilt Tomcat configuration provided for such scenario?
The standard Java EE approach for this would be as follows:
Instead of doing all the processing in the web-layer, put all the details on a JMS queue and return the request straight away.
The data would be taken off the JMS queue by a worker (possibly on a different server, as you wouldn't want to have the load of creating something for 15 minutes on your web layer)
Once the data is create for the user a notification would be generated (e.g. the browser could query every 30 seconds whether the user generation has finished).
N.B. blocking a thread in a server for 15 minutes is a very bad idea, because essentially it means that your servlet container wouldn't be able to do anything else with that thread. Imagine if a large number of those requests came in at the same time, your web layer would probably buckle under the pressure...
N.B.2: 15*50 does not make 15 minutes

Categories