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.
Related
I am using HttpURLConnection in my Java (Spring) app to send HTTP requests to external third-party servers. I need about 1000 http requests per second.
However, IMHO HttpURLConnection is synchronous, thus one thread can only do one http request, and only after that request is finished, this thread can do the next request. Therefore, this seems to be non-efficient, and I suspect this cannot even be handled (please correct me if I am wrong, e.g. this is actually very efficient).
I wonder whether there is a good way to handle these? IMHO I will use a thread pool (Executor) containing, say, 100 threads.
P.S. I cannot use any other libraries such as HttpClient since that SDK package is provided by third party :/
Thanks very much!
1.You are right about the request in one Thread.It is mentioned in the HttpURLConnection document
* Each HttpURLConnection instance is used to make a single request
* but the underlying network connection to the HTTP server may be
* transparently shared by other instances. Calling the close() methods
* on the InputStream or OutputStream of an HttpURLConnection
* after a request may free network resources associated with this
* instance but has no effect on any shared persistent connection.
* Calling the disconnect() method may close the underlying socket
* if a persistent connection is otherwise idle at that time.
*
That means that you could use openConnection to get a new HttpURLConnection instance,then do request and close that.The the underlying network connection to the HTTP server may be transparently shared by other instance.
Socket and SocketChannels might be a good option, although you'll have to 'roll your own' HTTP, which will be Very Not Easy if you have to deal with HTTPS. They are part of the standard JRE and can also be used asynchronously. You get into some hairy code when you go async because the Selector API is a bit difficult to work with but it would definitely be fast and have low overhead.
You might be able to use a custom SSLSocketFactory to jocky the socket so that you have direct access to the socket to get a SocketChannel from.
This question already has answers here:
Best Practice to Use HttpClient in Multithreaded Environment
(5 answers)
Closed 4 years ago.
I've a query regarding HttpClient.
Do you think for a multi-threaded application, is it a good idea to instantiate a new HttpClient object for each and every incoming request?
HttpClients.custom()
.setConnectionManager(new PoolingHttpClientConnectionManager())
.build();
If not, then in that case we will have only one HttpClient object. Now that singleton HttpClient object can be shared by many threads for rest call execution.
Upon successful execution of our rest call, we usually close the httpclient object inside finally block using HttpClients.closequietly()
Don't you think that closing the singleton httpclient object will create problems in a multi-threaded environment.
How should we handle the scenario then?
As far as I know, it's absolutely fine to use a single instance of HttpClient in multiple threads. In order to handle rest call properly, you need close rest call response, for example, org.apache.http.util.EntityUtils#consumeQuietly can be used.
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.
In Java EE7, the JAX-RS Client API provides a high-level API for accessing any REST resources. According to the documentation, "Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application. "
In order to avoid create client frequently, I am going to cache the client instance and reuse it. Is the client instance thread safe since it can be used by concurrent threads?
Is there any performance issue if I only create a instance of the client and reuse it for all the requests?
I am not sure but I think this is a implementation-specific decision.
I couldn't find in the JAX-RS 2.0 specification nor in the Javadoc anything granting that javax.ws.rs.client.Client is thread-safe. But in the Resteasy (an implementor of JAX-RS) documentation I found:
One default decision made by HttpClient and adopted by Resteasy is the
use of org.apache.http.impl.conn.SingleClientConnManager, which
manages a single socket at any given time and which supports the use
case in which one or more invocations are made serially from a single
thread. For multithreaded applications, SingleClientConnManager may be
replaced by
org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager:
ClientConnectionManager cm = new ThreadSafeClientConnManager();
HttpClient httpClient = new DefaultHttpClient(cm);
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
Source: http://docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html/RESTEasy_Client_Framework.html#transport_layer
Based in these information I guess that the answer for your question is likely to be "no".
PLEASE BE AWARE: Although this is the accepted answer, this is implementation specific and was correct for the Jersey 1 Client. For that you absolutely should share a single instance. Creating a client per request is a huge performance overhead
The JavaDoc is mostly answering your question already- yes it's thread-safe and you can and should reuse it. There can be a performance issue from not reusing it, i.e. if you create a Client for every HTTP request you make your performance will suck really bad.
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.