【发布时间】:2020-08-05 06:48:25
【问题描述】:
我一直在开发一个中小型 Web 应用程序,大约有 10 个端点。它应该可以同时处理数百个并发请求。
由于我的公司政策,我不得不为我的控制器使用javax.ws.rs,所以每个控制器方法都返回一个javax.ws.rs.core.Response
每个控制器都依赖一个Service,它负责去数据库(DynamoDB,使用v2非阻塞java dynamoDb sdk),通过http从其他微服务获取数据(使用org.asynhttpclient),并创建案例代表我的响应的类,因此我的控制器可以序列化它并将其作为 javax.ws.rs.core.Response 中的主体返回。
我的应用程序中的每个组件都是异步且非阻塞的,我的服务返回Future[Either[MyAppError, CaseClassRepresentingMyResponse]]。然后,在控制器中,就在最后我等待未来的结果,并创建javax.ws.rs.core.Response:
所以我的控制器看起来像这样:
class BarController(barService: BarService)(implicit ec: ExecutionContext) {
def getFoo(userId: BigInt, fooId: String): Response = withMetrics(Bar.ServiceName, Bar.GetFoo) {
val fooResponse = for {
_ <- EitherT(validateUserIdAndFooId(userId, fooId))
foo <- EitherT(barServiceService.getFoo(userId, fooId))
} yield foo
Await.result(fooResponse.value, 10 seconds) match {
case Success(Right(r)) => buildOkResponse(r)
case Success(Left(NotFound)) => HttpResponses.notFound
(.... a bunch of other cases ......)
}
}
}
(我正在使用猫 EitherT 来处理Future[Either[E, A]]。)
我的应用程序中的每个组件都会收到一个隐含的ExecutionContext,并返回一个Future[Either[E,A]]。
现在,我刚刚完成了所有的编码和测试,我需要在我的配置中提供一个正确的ExecutionContext。
ExecutionContext.global 够吗?考虑到我的代码从不阻塞(因为我使用的是 DynamoDb 非阻塞 sdk 和 org.asynchttpclient),还是应该创建一个不同的 ExecutionContext?也许来自 FixedThreadPool?还是 ForkJoinPool?
【问题讨论】:
-
我猜你现在可能只使用 global 和基准测试,如果你开始遇到问题,你可以尝试使用自定义调整它。
-
Await.result肯定会阻止,请改用future.onComplete {...}。
标签: scala asynchronous future nonblocking