我正在尝试测试一个基本的阻塞和非阻塞API控制器,它会像下面那样传输OkHttp
响应:
@SpringBootApplication
public class HttpProxyServiceApplication {
public static void main(String[] args) {
SpringApplication.run(HttpProxyServiceApplication.class, args);
}
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
@RestController
@RequestMapping(path = "/test")
public static class TestController {
private static final String URL = ...;
@Autowired
private OkHttpClient client;
@RequestMapping(method = RequestMethod.GET, path = "blocking")
public void blocking(HttpServletResponse httpServletResponse) throws IOException {
Request request = new Request.Builder()
.url(URL)
.build();
try (ResponseBody body = client.newCall(request).execute().body()) {
StreamUtils.copy(body.byteStream(), httpServletResponse.getOutputStream());
}
}
@RequestMapping(method = RequestMethod.GET, path = "non-blocking")
public DeferredResult<ResponseEntity<?>> nonBlocking() {
Request request = new Request.Builder()
.url(URL)
.build();
DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
ResponseEntity<Void> responseEntity =
new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE);
deferredResult.setResult(responseEntity);
}
@Override
public void onResponse(Response response) throws IOException {
ResponseEntity<InputStreamResource> responseEntity =
new ResponseEntity<>(new InputStreamResource(response.body().byteStream()),
HttpStatus.ACCEPTED);
deferredResult.setResult(responseEntity);
}
});
return deferredResult;
}
}
}
重要的事情:我想要传输结果!我不想将整个结果保存在内存中。这就是为什么非阻塞我创建了ResponseEntity<InputStreamResource>
。
然而,使用在两个API上进行爬网的基本JMeter脚本,非阻塞实际上比阻塞的速度慢
阻止结果:
非阻止结果:
有什么理由吗?
更新1:
新测试
@RequestMapping(method = RequestMethod.GET, path = "non-blocking-2")
public DeferredResult<InputStreamResource> nonBlockingBlocking() throws IOException {
Request request = new Request.Builder()
.url(URL)
.build();
DeferredResult<InputStreamResource> deferredResult = new DeferredResult<>();
deferredResult.setResult(new InputStreamResource(client.newCall(request).execute().body().byteStream()));
return deferredResult;
}
与完全阻止类似的结果。所以我不认为性能问题直接来自DeferredResult
。