我们有一个向用户提供Feed的移动应用。 feed tom API是在tomcat上实现的,它并行调用不同的数据源,如Couchbase,MYSQL来呈现内容。简单的代码如下:
Future<List<CardDTO>> pnrFuture = null;
Future<List<CardDTO>> newsFuture = null;
ExecutionContext ec = ExecutionContexts.fromExecutorService(executor);
final List<CardDTO> combinedDTOs = new ArrayList<CardDTO>();
// Array list of futures
List<Future<List<CardDTO>>> futures = new ArrayList<Future<List<CardDTO>>>();
futures.add(future(new PNRFuture(pnrService, userId), ec));
futures.add(future(new NewsFuture(newsService, userId), ec));
futures.add(future(new SettingsFuture(userPreferenceManager, userId), ec));
Future<Iterable<List<CardDTO>>> futuresSequence = sequence(futures, ec);
// combine the cards
Future<List<CardDTO>> futureSum = futuresSequence.map(
new Mapper<Iterable<List<CardDTO>>, List<CardDTO>>() {
@Override
public List<CardDTO> apply(Iterable<List<CardDTO>> allDTOs) {
for (List<CardDTO> cardDTOs : allDTOs) {
if (cardDTOs != null) {
combinedDTOs.addAll(cardDTOs);
}
}
Collections.sort(combinedDTOs);
return combinedDTOs;
}
}
);
Await.result(futureSum, Duration.Inf());
return combinedDTOs;
现在我们每个请求有大约4-5个并行任务。但随着我们在饲料中引入新种类的物品,预计它将增长到近20-25个并行任务。
我的问题是,我该如何改进这个设计? Tomcat需要进行何种调整才能确保在重负载下最佳地提供20-25个并行调用。
我知道这是一个广泛的主题,但任何建议都会非常有用。
答案 0 :(得分:7)
Tomcat只管理传入的HTTP连接并来回推送字节。没有Tomcat优化可以使您的应用程序运行得更好。
如果您需要为每个传入的HTTP请求运行25个并行进程,并且您认为这很疯狂,那么您需要重新考虑应用程序的工作方式。
没有tomcat配置可以帮助您在问题中提供的内容。
答案 1 :(得分:4)
看起来你使用的是Akka,但并不真正拥抱Actor模型,这样做可能会增加应用程序的并行性和可扩展性。
如果是我,我会将请求从我的REST API发送到一个或一组协调参与者,这些参与者将异步处理请求。使用Spring的RestController可以使用Callable
或DeferredResult
来完成,但是在你使用的任何框架中显然都会有一个等价物。
然后,这个协调参与者将处理交给处理I / O绑定任务的其他参与者(即工作者)(最好使用他们自己的调度程序以确保其他CPU绑定线程不被阻止)并响应协调员及其结果。
一旦所有工作人员获取了他们的数据并用结果回复协调员,那么可以使用完整的结果集完成原始请求。
答案 2 :(得分:4)
我知道您是通过移动应用程序调用此功能,并且可以提高Feed数量。
根据返回的数据量,是否可以在同一个调用中返回某些Feed的结果? 这样服务器就能完成工作。 您可以控制服务器 - 您无法控制用户设备及其连接速度。
正如nickebbit建议的那样,像DefferedResult这样的东西真的很容易实现。 是否可能无法快速更新来自这些Feed的数据?如果是这样 - 您应该调查EHCache和@Cacheable注释的使用。
您可以提出一个解决方案,用户始终从tomcat服务器中提取内容的缓存版本。但是你的tomcat服务器在后台不断更新缓存。
这是一项额外的工作 - 但如果用户体验不快,那么在一天结束时 - 用户将不想使用此应用程序