我有一个正在使用的客户库和传入DataRequest
对象拥有userid
,timeout
并且在它的一些其他领域.现在我使用这个DataRequest
对象创建一个URL,然后我使用了一个HTTP调用RestTemplate
,我的服务返回一个JSON响应,我用它来创建一个DataResponse
对象并将这个DataResponse
对象返回给它们.
以下是DataClient
客户通过将DataRequest
对象传递给我的类.DataRequest
如果在getSyncData
方法中花费太多时间,我正在使用客户传递的超时值来超时请求.
public class DataClient implements Client { private RestTemplate restTemplate = new RestTemplate(); // first executor private ExecutorService service = Executors.newFixedThreadPool(15); @Override public DataResponse getSyncData(DataRequest key) { DataResponse response = null; FutureresponseFuture = null; try { responseFuture = getAsyncData(key); response = responseFuture.get(key.getTimeout(), key.getTimeoutUnit()); } catch (TimeoutException ex) { response = new DataResponse(DataErrorEnum.CLIENT_TIMEOUT, DataStatusEnum.ERROR); responseFuture.cancel(true); // logging exception here } return response; } @Override public Future getAsyncData(DataRequest key) { DataFetcherTask task = new DataFetcherTask(key, restTemplate); Future future = service.submit(task); return future; } }
DataFetcherTask
类:
public class DataFetcherTask implements Callable{ private DataRequest key; private RestTemplate restTemplate; public DataFetcherTask(DataRequest key, RestTemplate restTemplate) { this.key = key; this.restTemplate = restTemplate; } @Override public DataResponse call() throws Exception { // In a nutshell below is what I am doing here. // 1. Make an url using DataRequest key. // 2. And then execute the url RestTemplate. // 3. Make a DataResponse object and return it. // I am calling this whole logic in call method as LogicA } }
截至目前,我的DataFetcherTask
班级负责一个DataRequest
密钥,如上所示..
问题陈述:-
现在我有一个小的设计变化.客户将DataRequest
(例如keyA)对象传递给我的库,然后我将通过使用DataRequest
(keyA)对象中存在的用户ID来对另一个服务(我在当前设计中没有做)进行新的http调用用户ID的列表,所以我将使用这些用户ID,并DataRequest
为响应中返回的每个用户ID创建一个其他(keyB,keyC,keyD)对象.然后我将拥有List
具有keyB,keyC和keyD DataRequest
对象的对象.List
将是三个中的最大元素,就是全部.
现在对于每个DataRequest
对象,List
我想DataFetcherTask.call
并行执行上面的方法,然后List
通过DataResponse
为每个键添加每个.所以我将有三个并行调用DataFetcherTask.call
.此并行调用背后的想法是在相同的全局超时值中获取所有这三个最大键的数据.
所以我的建议是 - DataFetcherTask
类将返回List
对象而不是DataResponse
然后签名getSyncData
和getAsyncData
方法也会改变.所以这是算法:
使用客户传递的DataRequest对象通过List
调用另一个HTTP服务来进行.
对方法中的每个DataRequest
进行并行调用,而不是将对象返回给客户.List
DataFetcherTask.call
List
DataResponse
通过这种方式,我可以在步骤1中应用相同的全局超时以及步骤2.如果上述步骤中的任何一个花费时间,我们将在getSyncData
方法中超时.
DataFetcherTask
设计变更后的课程:
public class DataFetcherTask implements Callable> { private DataRequest key; private RestTemplate restTemplate; // second executor here private ExecutorService executorService = Executors.newFixedThreadPool(10); public DataFetcherTask(DataRequest key, RestTemplate restTemplate) { this.key = key; this.restTemplate = restTemplate; } @Override public List
call() throws Exception { List keys = generateKeys(); CompletionService comp = new ExecutorCompletionService<>(executorService); int count = 0; for (final DataRequest key : keys) { comp.submit(new Callable () { @Override public DataResponse call() throws Exception { return performDataRequest(key); } }); } List responseList = new ArrayList (); while (count-- > 0) { Future future = comp.take(); responseList.add(future.get()); } return responseList; } // In this method I am making a HTTP call to another service // and then I will make List accordingly. private List generateKeys() { List keys = new ArrayList<>(); // use key object which is passed in contructor to make HTTP call to another service // and then make List of DataRequest object and return keys. return keys; } private DataResponse performDataRequest(DataRequest key) { // This will have all LogicA code here which is shown in my original design. // everything as it is same.. } }
现在我的问题是 -
它必须是这样的吗?解决这个问题的正确设计是什么?我的意思是让call
另一种call
方法的方法看起来很奇怪?
我们需要在代码中拥有两个执行器吗?有没有更好的方法来解决这个问题或我们可以在这里做的任何简化/设计变更?
我已经简化了代码,以便想法清楚我想要做什么.