At the moment i am trying to find the best way to manage concurrent API Calls within my application. Currently i have been using HTTPURLConnection to make my HTTP method calls and although it works fine, eventually i would come across some 'Socket exception: connection reset' whilst calls are being made. however, i am using multithreading as i have many different api calls running concurrently.
I have looked into using AsyncRestTemplate and although it is working i find that in the console a list of the pool and thread is shown i.e [pool-6-thread-1] however when it becomes [pool-2018-thread-1] that is when it decides to stop making any more api calls.
This is the code that i am using:
//This method is inside another class in my actual application but here for simplicity
public static ListenableFuture<ResponseEntity<String>> getLastPrice( AsyncRestTemplate asyncRestTemplate) {
String url = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-dar";
asyncRestTemplate = new AsyncRestTemplate(new ConcurrentTaskExecutor(Executors.newCachedThreadPool()));
return asyncRestTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>("result"), String.class);
}
public PriceThread(JTextField lastPriceJT) {
this.lastPriceJT = lastPriceJT;
}
#Override
public void run() {
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(new ThreadPoolTaskExecutor());
while (true) {
try {
getLastPrice(coin, asyncRestTemplate)
.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
#Override
public void onSuccess(ResponseEntity<String> response) {
//TODO: Add real response handling
try {
JSONObject result = new JSONObject(response.getBody());
String status = LOGGER.printResponseToLogger(result);
BigDecimal last = result.getJSONArray("result").getJSONObject(0).getBigDecimal("Last");
lastPriceJT.setText(last.toPlainString());
} catch (Exception e) {
LOGGER.printResponseToLogger(e.getMessage());
}
}
#Override
public void onFailure(Throwable ex) {
//TODO: Add real logging solution
LOGGER.printResponseToLogger(ex.getMessage());
}
});
} catch (Exception e) {
LOGGER.printResponseToLogger(e.getMessage());
}
}
}
Currently i'm thinking the solution to this issue would be for me to reuse the pools so that it doesn't increment to 2018 if that is possible but i have not found a way to do so.
Related
I have a Server that can receive multiple request at the same time.
In my Server, I have to make some traitement and wait for response. This traitmenet is done by externe library so I don't how much should I wait.
So the Server looks like :
public class MyServer{
#Override
//method from the library
public void workonRequest(){
//---
response=[...]
}
public void listenRequest() {
new Thread(() -> {
while (true) {
try {
socket = server.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
socket.setTcpNoDelay(true); //TODO : Not sure !
new Thread(() -> {
try {
handleRequest(input, output);
} catch (IOException e) {
throw new RuntimeException(e);
}
}).start();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}).start();
}
And the handle request method is :
public void handleRequest(ObjectInputStream input, ObjectOutputStream output) throws IOException {
try {
while (true) {
//forward the request to the library
//work on it [means using the library and waiting]
// return response
}
}
}
The response object is the result that I want return to the client
How to deal with the problem of waiting for the answer?
How can I make sure that there will be no problems when more than 2 clients send requests at the same time.
Thanks in advance
How to deal with the problem of waiting for the answer ?###
Using while(true) can create issues because you are blocking the thread and opening sub thread and multi streams will make it more complex. There is easy way called reactive programming which handles this kind of multi-threaded issues easily, quarkus async solution and spring, if you still want to manage your sockets from java code you can use akka
How can I make sure that there will be no problems when more than 2 clients send requests at the same time.
That can be done by not blocking the main thread and If you manage to use reactive and/or async approach you will not have that problem.
Reference
https://quarkus.io/guides/getting-started-reactive
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html
I'm new to vert.x and would like to know if its possible to configure eventbus somehow to make it work consistently?
I mean need to send requests one by one using vert.x
At the moment I got this code which uses eventloop principle and waits until all handlers finished, but I don't need this done that fast, idea is to free server from lots of requests at the same time. Here eb_send() uses default EventBus.send() method. In other words I want to execute all requests with blocking, waiting for answers before requests.
List<Future> queue = new ArrayList<>();
files.forEach(fileObj -> {
Future<JsonObject> trashStatusHandler = Future.future();
queue.add(trashStatusHandler);
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
} catch (Exception ex) {
log.error(ex);
}
trashStatusHandler.complete();
});
});
The basic idea is to extract this into a function, which you would invoke recursively.
public void sendFile(List<File> files, AtomicInteger c) {
eb_send(segment, StorageType.getAddress(StorageType.getStorageType(fileInfo.getString("storageType"))) + ".getTrashStatus", fileInfo, reply -> {
Entity dummy = createDummySegment();
try {
if (reply.succeeded()) {
//succeded
}
// Recursion
if (c.incrementAndGet() < files.size()) {
sendFile(files, c);
}
} catch (Exception ex) {
log.error(ex);
}
});
}
I am debugging an issue in my android app. I found the root cause is file descriptors went beyond the limit. After further investigation I found that the app has too many sockets open. I use OkHttpClient 2.5 for all of my network communication, thus I am wondering how should I limit my connection pool size. Below is my code snippet:
OkHttpClient okHttpClient = new OkHttpClient().setConnectTimeout(TIMEOUT);
ConnectionPool connectionPool = new ConnectionPool(MAX_IDLE_CONNECTIONS,
KEEP_ALIVE_DURATION_MS);
okHttpClient.set(connectionPool);
#RequireArgsConstructor
public HttpEngineCallable implements Callable<IHttpResponse>
{
private final String url;
public IHttpResponse call () throws Exception
{
try
{
Request request = Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
Response rawResponse = call.execute();
return new OkHttpResponse(rawResponse);
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
private final Function<IHttpResponse, T> httpResponseParser = new Function<IHttpResponse, T>()
{
#Nullable
#Override
public T apply(#Nullable IHttpResponse httpResponse)
{
if(httpResponse == null)
{
return null;
}
InputStream stream = httpResponse.getBody();
JsonParser parser = null;
T result = null;
try
{
parser = jsonFactory.createParser(stream);
result = strategy.parseData(parser);
}
catch (Exception e)
{
log.error("Unable to convert {} with {}.", stream, strategy, e);
}
finally
{
IOUtils.closeQuietly(parser);
IOUtils.closeQuietly(stream);
}
return result;
}
};
Future<T> future = executorService.submit(new HttpEngineCallable(url));
Future<V> finalFuture = Futures.transform(future, httpResponseParser, executorService);
T result = timeoutExecutorService.submit(new Runnable()
{
try
{
T result = finalFuture.get(CLIENT_TIMEOUT, TIMEUNIT)
if (result == null)
{
notify onFailure listeners
}
else
{
notify onSuccess Listeners
}
}
catch(Exception ex)
{
notify onFailure listeners
}
}
So I have a few questions regarding this implementation:
My CLIENT_TIMEOUT is shorter than OkHttp ConnectTimeout. If my finalFuture.get(CLINT_TIMEOUT, TIMEUNIT) throws timeout exception, would my finally block in the Parser Function still be executed? I am counting on it to close my connection.
How can limits the size of my ConnectionPool? Is there way I can auto-recycle oldest connections if connection went beyond limit?
We had a similar issue with too many open file descriptors crashing our app.
The problem was that we created one OkHttpClient per request. By default each OkHttpClient comes with its own connection pool, which of course blows up the number of connections/threads/file handles and prevents proper reuse in the pool.
We solved the problem by manually creating a global ConnectionPool in a singleton, and then passing that to the OkHttpClient.Builder object which builds the actual OkHttpClient.
...
builder.connectionPool(GLOBAL_CONNECTION_POOL);
OkHttpClient client = builder.build();
...
This still allows for per-request configuration using the OkHttpClient.Builder and makes sure all OkHttpClient instances are still using a common connection pool.
We were then able to properly size the global connection pool.
I am trying to teach myself some networking in Java using the Kryonet library. The following code is almost identical to the code in the kyronet tutorial. https://code.google.com/p/kryonet/#Running_a_server
The client is successfully sending the message "Here is the request!" to the server (the server is printing it out) however the client is not receiving any response from the server even though the server is sending one.
I've tried unsuccessfully to fix it, can anyone see or suggest a possible problem/solution with the code?
(The code follows)
Client
public class Client_test {
Client client = new Client();
public Client_test() {
Kryo kryo = client.getKryo();
kryo.register(SomeRequest.class);
kryo.register(SomeResponse.class);
client.start();
try {
client.connect(50000, "127.0.0.1", 54555, 54777);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
client.addListener(new Listener() {
public void received (Connection connection, Object object) {
if (object instanceof SomeResponse) {
SomeResponse response = (SomeResponse)object;
System.out.println(response.text);
}
}
});
SomeRequest request = new SomeRequest();
request.text = "Here is the request!";
client.sendTCP(request);
}
}
Server
public class ServerGame {
Server server = new Server();
public ServerGame() {
Kryo kryo = server.getKryo();
kryo.register(SomeRequest.class);
kryo.register(SomeResponse.class);
server.start();
try {
server.bind(54555, 54777);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
server.addListener(new Listener() {
public void received (Connection connection, Object object) {
if (object instanceof SomeRequest) {
SomeRequest request = (SomeRequest)object;
System.out.println(request.text);
SomeResponse response = new SomeResponse();
response.text = "Thanks!";
connection.sendTCP(response);
}
}
});
}
}
Response & Request classes
public class SomeRequest {
public String text;
public SomeRequest(){}
}
public class SomeResponse {
public String text;
public SomeResponse(){}
}
After many hours watching youtube videos and sifting through the web I found the answer. Which I will post on here as it seems that quite a few people have had this problem so I would like to spread the word.
Basically the client would shut down immediately, before it could receive and output the message packet. This is because "Starting with r122, client update threads were made into daemon threads, causing the child processes to close as soon as they finish initializing.", the solution is "Maybe you could use this? new Thread(client).start();".
So basically instead of using
client.start();
to start the client thread you must use
new Thread(client).start();
Which I believe stops the thread being made into a daemon thread which therefore stops the problem.
Source: https://groups.google.com/forum/?fromgroups#!topic/kryonet-users/QTHiVmqljgE
Yes, inject a tool like Fiddler in between the two so you can see the traffic going back and forth. It's always easier to debug with greater transparency, more information.
I have a home grown web server in my app. This web server spawns a new thread for every request that comes into the socket to be accepted. I want the web server to wait until a specific point is hit in the thread it just created.
I have been through many posts on this site and examples on the web, but cant get the web server to proceed after I tell the thread to wait. A basic code example would be great.
Is the synchronized keyword the correct way to go about this? If so, how can this be achieved? Code examples are below of my app:
Web Server
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.run();
///////////////////////////////
wait here until notifed to proceed
///////////////////////////////
} catch (Exception e) {
e.printStackTrace(logFile);
}
}
Thread code
public void run() {
//code here
//notify web server to continue here
}
Update - Final code is as below. The HttpRequest does just call resumeListener.resume() whenever I send a response header (of course also adding the interface as a separate class and the addResumeListener(ResumeListener r1) method in HttpRequest):
Web Server portion
// server infinite loop
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
request.addResumeListener(new ResumeListener() {
public void resume() {
//get control of the lock and release the server
synchronized(locker) {
locker.notify();
}
}
});
synchronized(locker) {
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.start();
//tell this thread to wait until HttpRequest releases
//the server
locker.wait();
}
} catch (Exception e) {
e.printStackTrace(Session.logFile);
}
}
You can use java.util.concurrent.CountDownLatch with a count of 1 for this. Arrange for an instance of it to be created and shared by the parent and child thread (for example, create it in HttpRequest's constructor, and have it retrievable by a member function). The server then calls await() on it, and the thread hits countDown() when it's ready to release its parent.
You probably need to use a Java Condition. From the docs:
Conditions (also known as condition
queues or condition variables) provide
a means for one thread to suspend
execution (to "wait") until notified
by another thread that some state
condition may now be true.
First of all, I echo the sentiment of others that re-inventing the wheel here will most likely lead to a variety of issues for you. However, if you want to go down this road anyway what you are trying to do is not difficult. Have you experimented with Jetty?
Maybe something like this:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
Run under a debugger and set a breakpoint?
If unfeasible, then read a line from System.in?