Set timeout on thread execution and save return value

2

Hello,

I have a web service, with a backend in java 7. At some point, the backend makes an RPC call in broadcast to N servers that are listening. But there is no pre-defined timeout on the call, I have no way to control the response time of the N servers. I do not have access to the source code of the N servers.

result = RPC.call(params, liveAddresses, conf);

The proposed solution was to convert the code to multi-threading by creating N threads. Each is responsible for calling 1 address (server). If you follow the previous strategy:

It is possible in Java to launch multiple threads with a maximum wait time that each ends. Getting thread main results from all threads?

I accept ideas for other strategies to follow.

Thank you.

    
asked by anonymous 12.10.2017 / 00:04

1 answer

2

An alternative would be to use ExecutorService

Basic Example:

RpcResult.class:

public class RpcResult {

  private int clientId;
  private String response;

  // getters and setters...
}

RpcExecutor.class:

public class RpcExecutor implements Callable<RpcResult>{

  private int clientId;

  public RpcExecutor(int clientId) {
    this.clientId = clientId;
  }

  public RpcResult call() throws Exception {    
    RpcResult result = new RpcResult();
    result.setClientId(clientId);
    result.setResponse("Resposta do cliente: " + clientId);

    return result;
  }

}

Execution:

ExecutorService executor = Executors.newFixedThreadPool(3);             
List<Callable<RpcResult>> list = new ArrayList<Callable<RpcResult>>();

for (int i = 1; i <= 3; i++) {
  list.add(new RpcExecutor(i));        
}

// 3 segundos de timeout
List<Future<RpcResult>> future = executor.invokeAll(list, 3L, TimeUnit.SECONDS);

for(Future<RpcResult> f : future) {           
  try {
    if (!f.isCancelled()) {
      RpcResult result = f.get();
      System.out.println(result.getClientId());
      System.out.println(result.getResponse());
    }
  } catch (InterruptedException e) {
    e.printStackTrace();
  } catch (ExecutionException e) {
    e.printStackTrace();
  }      
};

executor.shutdown();

To simulate a client's timeout, simply add a Thread.sleep () method in the call () method of the RpcExecutor class:

public RpcResult call() throws Exception {
    if (clientId == 2)
        Thread.sleep(15000);

    RpcResult result = new RpcResult();
    result.setClientId(clientId);
    result.setResponse("Resposta do cliente: " + clientId);

    return result;
}

EDIT

According to the new information related to the current project structure, this solution would not have scalability.

If you have in mind that your application will never have many users, okay, go in the simplest solution. Now, if your application needs to scale, this could be one of the alternatives (simplified model):

    
12.10.2017 / 04:01