如果没有 AsyncResponse,性能与 ExecutorService 相同。如果多个 API 调用必须异步并且链接起来,那么这种方法更好(类似 Node 中的 Promises)。
- ExecutorService ioExecutorService = CustomThreads.getExecutorService(ioPoolSize);
-
- // I/O 任务
- CompletableFuture<String> postsFuture = CompletableFuture.supplyAsync(JsonService::getPosts, ioExecutorService);
- CompletableFuture<String> commentsFuture = CompletableFuture.supplyAsync(JsonService::getComments,
- ioExecutorService);
- CompletableFuture<String> albumsFuture = CompletableFuture.supplyAsync(JsonService::getAlbums,
- ioExecutorService);
- CompletableFuture<String> photosFuture = CompletableFuture.supplyAsync(JsonService::getPhotos,
- ioExecutorService);
- CompletableFuture.allOf(postsFuture, commentsFuture, albumsFuture, photosFuture).get();
-
- // 从 I/O 任务(阻塞调用)获得响应
- String posts = postsFuture.get();
- String comments = commentsFuture.get();
- String albums = albumsFuture.get();
- String photos = photosFuture.get();
-
- // 合并响应(内存中的任务将是此操作的一部分)
- String postsAndCommentsOfRandomUser = ResponseUtil.getPostsAndCommentsOfRandomUser(userId, posts, comments);
- String albumsAndPhotosOfRandomUser = ResponseUtil.getAlbumsAndPhotosOfRandomUser(userId, albums, photos);
-
- // 构建最终响应并将其发送回客户端
- return postsAndCommentsOfRandomUser + albumsAndPhotosOfRandomUser;
7. 使用 ExecutorService 并行处理所有任务
使用 ExecutorService 并行处理所有任务,并使用 @suspended AsyncResponse response 以非阻塞方式发送响应。
图片来自 http://tutorials.jenkov.com/java-nio/nio-vs-io.html
- HTTP 线程处理传入请求的连接,并将处理传递给 Executor Pool,当所有任务完成后,另一个 HTTP 线程将把响应发送回客户端(异步非阻塞)。
- 性能下降原因:
- 在同步通信中,尽管 I/O 任务中涉及的线程被阻塞,但是只要进程有额外的线程来承担并发请求负载,它仍然处于运行状态。
- 因此,以非阻塞方式保持线程所带来的好处非常少,而且在此模式中处理请求所涉及的成本似乎很高。
- 通常,对这里讨论采用的例子使用异步非阻塞方法会降低应用程序的性能。
7.1 何时使用?
如果用例类似于服务器端聊天应用程序,在客户端响应之前,线程不需要保持连接,那么异步、非阻塞方法比同步通信更受欢迎。在这些用例中,系统资源可以通过异步、非阻塞方法得到更好的利用,而不仅仅是等待。
- // 为异步执行提交并行任务
- ExecutorService ioExecutorService = CustomThreads.getExecutorService(ioPoolSize);
- CompletableFuture<String> postsFuture = CompletableFuture.supplyAsync(JsonService::getPosts, ioExecutorService);
- CompletableFuture<String> commentsFuture = CompletableFuture.supplyAsync(JsonService::getComments,
- ioExecutorService);
- CompletableFuture<String> albumsFuture = CompletableFuture.supplyAsync(JsonService::getAlbums,
- ioExecutorService);
- CompletableFuture<String> photosFuture = CompletableFuture.supplyAsync(JsonService::getPhotos,
- ioExecutorService);
-
- // 当 /posts API 返回响应时,它将与来自 /comments API 的响应结合在一起
- // 作为这个操作的一部分,将执行内存中的一些任务
- CompletableFuture<String> postsAndCommentsFuture = postsFuture.thenCombineAsync(commentsFuture,
- (posts, comments) -> ResponseUtil.getPostsAndCommentsOfRandomUser(userId, posts, comments),
- ioExecutorService);
-
- // 当 /albums API 返回响应时,它将与来自 /photos API 的响应结合在一起
- // 作为这个操作的一部分,将执行内存中的一些任务
- CompletableFuture<String> albumsAndPhotosFuture = albumsFuture.thenCombineAsync(photosFuture,
- (albums, photos) -> ResponseUtil.getAlbumsAndPhotosOfRandomUser(userId, albums, photos),
- ioExecutorService);
-
- // 构建最终响应并恢复 http 连接,把响应发送回客户端
- postsAndCommentsFuture.thenAcceptBothAsync(albumsAndPhotosFuture, (s1, s2) -> {
- LOG.info("Building Async Response in Thread " + Thread.currentThread().getName());
- String response = s1 + s2;
- asyncHttpResponse.resume(response);
- }, ioExecutorService);
(编辑:ASP站长网)
|