Unable to make a non blocking http request in minecraft mod - java

I'm creating a mod that needs to call a GET request to an endpoint.
I don't care about any result, I just want the request to be sent.
Right now I'm using
HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
And it will block. Because the api takes some time to respond that's not good.
I saw that there's a library called async-http-client but I can't add libraries to my project.
I guess I have to create threads in my mod but that doesn't look like the best solution to me as minecraft mods shouldn't make new threads.
Is there any java package that won't care about the response?

Sending network traffic will always block until it's completed - there's no way around that. In this case it should be perfectly fine to create a new thread to do that actual work - the thread will just block (and not waste CPU resources) for most of the time.
Note that async-http-client will just create it's own threads to do it's work, so it won't help get around this restriction.

Related

REST API request timeout for services which are always slow

I am working on a project where I have to call a third-party REST service. The problem with the current setup is that service does not return in at least 16 seconds. This response time may exceed more than that.
To avoid the threads waiting on the server, my service has a timeout value of 16 seconds. But that value is not helping. I searched on this and found that the Circuit breaker pattern will be useful. Reference:- spring-boot-rest-api-request-timeout . I believe this pattern is useful when the service has a slow response a few times. In my case, it is always a slow service.
How can I tackle this scenario?
If you want the response from the third party REST service, you have no choise but to wait, but if your request method have other thing to do. You should use Callable Thread to sent request to REST service and let Main Thread to complete the other work first then wait for the Callable to come back.
Maybe you can try to use some Cache like #Cacheable or Redis for this scenario. It may speed up some of the similar request.
Or, just let your request method sent the response back to client first. After that, use AJAX to access the third party REST service from the client side.

Calling multiple asynchronous requests to Thrift Service from a single client

For my Code it is necessary to call multiple asynchronous Requests from the same client to a Thrift Service.
So I am using a Non blocking Server and Asynchronous Clients (see the code below) to allow asynchronous Calls, which means the execution of the code continues after the first call of the "checkForPrime()" Method, which I call on the Thrift Service.
Now this seems to work with only executing one call. If I make a second asynchronous call right after, I get the following error message:
Client is currently executing another method:
Interfaces.PrimeCheck$AsyncClient$checkForPrime_call
at
org.apache.thrift.async.TAsyncClient.checkReady(TAsyncClient.java:78)
at
Interfaces.PrimeCheck$AsyncClient.checkForPrime(PrimeCheck.java:110)
at ThriftClient.main(ThriftClient.java:40)
I need a smart solution to allow for multiple calls, but it has to be from the same client. Any suggestions are welcome. Please dont hesitate if you need further information.
org.apache.thrift.protocol.TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
TAsyncClientManager manager;
TNonblockingSocket socket;
AsyncClient client;
try {
manager = new TAsyncClientManager();
socket =new TNonblockingSocket("localhost", 4711);
client = new AsyncClient(factory, manager, socket);
client.checkForPrime(5, resultHandler);
client.checkForPrime(7, resultHandler);
Thread.sleep(100);
} catch (IOException e2) ....
to allow asynchronous Calls, which means the execution of the code continues after the first call of the "checkForPrime()" Method,
Not quite. Asynchronous only means that the call is completed asynchronously and you don't have to wait for the completion until necessary.
It does not imply that you can use the same client to do another parallel request. Some implementations may support this but the current implementation does not.
Multiple outstanding calls require some bookkeeping, otherwise you will get lost with the responses:
call 1 made --->
call 2 made --->
response arrives <----
response arrives <----
Now, what call does the first response belong to: call 1 or call 2? Hard to say, it could be either one. Without more information a multi-call client would have a hard time trying to correlate the data.
The TAsyncClientManager handles that by restricting clients to allowing only one pending call at a time.
it is necessary to call multiple asynchronous Requests from the same client
Why do you think it is necessary?
The client is only a mediator, a means of transport. If you send two emails, do you require the emails follow the exact same path across the interwebs? No, because the relevant information the other side (server) should rely on is in the message content, not in the transport level.
If, however, you need to store data at the client, you should store it in a dedicated place outside of the client instance. Either way, the fact that we deal with one or two client instances should not really matter.

HttpClient behaviour in multithreading and concurrent context

Can anyone help me to clarify how HttpClient behaves in multithreading?
When I create HttpClient object via the code below, should I keep the object globally across the app life cycle (this method is suggested in HttpClient doc), or should I create every time when I want to perform Http connection (Get and Post)?
1)
Static HttpClient httpclient = HttpClientBuilder.create().build(); //so we can use this object in everywhere.
2)
HttpClient httpclient = HttpClientBuilder.create().build(); //do this every time when we want to establish http connect.
What is the best way to make sure the Http connections will not block each other and to make sure they can run concurrently?
Use a PoolingConnectionManager and configure how many connections per route you need (make sure you have as many connections as you have threads using them). Then you can simply inject the same httpclient everywhere. I've been using it like this for several years.
Also consider using ResponseHandlers everywhere; this vastly simplifies releasing of resources and connections.

How to make work HttpResponse faster?

I am working on a project in which "I have to get 4096 bytes of data to server" from "server" every "between 1-millisecond to 10-millisecond".But it's "taking too much time" i.e "around 300ms - 700ms" which causes my application to lose data.
I am using below snippet
HttpClient client = new DefaultHttpClient();
HttpPost request = new HttpPost("http://192.168.1.40/ping");
HttpResponse response = client.execute(request);
The HttpResponse is only taking too much time i.e around 300ms - 700ms.
How I can get response faster ?
Instead of this what else I can use to get a response from sever faster then this?
Please let me know any solution or way to solve it.
I have done google, gone through other ways like DataOutputStream and ByteOutputStream but no use of this, it also taking too much time then HttpResponse.
Help will be appreciated.
Before you can make the responses faster, you are going to need to investigate and understand why they are currently taking a long time. Roughly speaking, it could be:
the client side taking a long time to create the request and/or preocess the result (seems unlikely ...)
a slow android network protocol stack
a problem with your local networking (e.g. WiFi) or your telecoms provider
a congested / overloaded server or server-side network, or
something pessimal in the server implementation.
Do things like:
try the request from a web browser on a conventional PC and use the browser's web-developer stuff to try to tease out whether/why the request is taking a long time ...
look in the server-side logs and/or monitoring for request load and timing information
other suggestions please
Implementing SPDY might help, but it is unlikely to change response times in the order of 500ms to a couple of tens of milliseconds. The problem seems more fundamental than "HTTP is old and slow". And the same reasoning applies to all of the other suggestions that people have made.
This is not possible. You are recreating a connection every time.
You need to hold a persistent connection with the server. Try creating a persistent http connection.
If that doesn't work you can try sending raw udp packets (or anything else). It will be harder but it will take less time.
#sheldonCooper answer is right if the server enables SPDY. Also you can add Gzip compression. It has been added to all requests after GingerBread but you could add it for former SDK versions : http://android-developers.blogspot.fr/2011/09/androids-http-clients.html
Use SPDY protocol. This would improve your response time.
I think in your case you can use websockets so that you would not have to create a connection each time and the live connection is available every time.

Apache HttpClient random delays under high requests/second

I'm using Apache HttpClient to query HTTP/1.0 (without keep alive) server on localhost with around 20 POST requests/second. I have a TCP_NODELAY enabled like this:
val httpParams = new BasicHttpParams()
HttpConnectionParams.setTcpNoDelay(httpParams, true)
val client = new DefaultHttpClient(connectionManager, httpParams)
Despite that, several times per minute I see a random delay of 10-200 milliseconds for sending such request (measuring on the server shows, that delay is in sending). I checked, that it's not a garbage collector pause. What can be the problem?
I tried to query the server with C++ client with the same rate, and it doesn't have such random delays, so i think it's HttpClient problem.
Update:
I checked jetty HttpClient implementation, and it has the same problem. Can this be some problem of JVM on FreeBSD? I should test this on linux, but I don't have a linux server at hand.
I have the same problem here using windows.
In my case, HttpClient was introducing around 1 second of delay but just at the first attempt to execute a post (I do several in sequence). I try a workaround that was to create a "fake" post to the local host and execute it (and except an IOException). By doing that, my delay when calling real services was reduce from around 1 second to around 100ms.
I could not improve more than that yet.

Categories

Resources