服务器端的异步和同步HTTP请求,性能比较

Jad*_*ang 12 java multithreading asynchronous http jmeter

我试图找出异步和同步HTTP请求处理的优缺点。我正在将Dropwizard和Jersey用作我的框架。测试是比较异步和同步HTTP请求处理,这是我的代码

@Path("/")
public class RootResource {

    ExecutorService executor;

    public RootResource(int threadPoolSize){
        executor = Executors.newFixedThreadPool(threadPoolSize);
    }

    @GET
    @Path("/sync")
    public String sayHello() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1L);
        return "ok";
    }

    @GET
    @Path("/async")
    public void sayHelloAsync(@Suspended final AsyncResponse asyncResponse) throws Exception {
        executor.submit(() -> {
            try {
                doSomeBusiness();
                asyncResponse.resume("ok");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }


    private void doSomeBusiness() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1L);
    }

}
Run Code Online (Sandbox Code Playgroud)

同步 API将在由码头和维护的工作线程运行的异步 API将主要运行在海关线程池。这是Jmeter的结果

  • 测试1,500个Jetty工作线程,/ sync端点

    在此处输入图片说明

  • 测试2,500个自定义线程,/ async端点

    在此处输入图片说明 结果表明,两种方法之间没有太大差异。

我的问题是:这两种方法之间有什么区别?在哪种情况下应该使用哪种模式?

相关主题:同步HTTP处理程序和异步HTTP处理程序之间的性能差异

更新


我按照建议的延迟进行了10次测试

  • 同步500服务器线程

同步500服务器线程

  • 异步500-workerthread

异步500-workerthread

RAJ*_*NAM 8

以下是我的想法。

无论是同步请求还是异步请求,都与HTTP的性能无关,但与应用程序的性能相关

同步请求将阻塞应用程序,直到它收到响应为止,而基本上在异步请求中,您将在一个单独的工作线程中分配此工作,该工作线程将负责其余的工作。因此,在异步设计中,您的主线程仍然可以继续自己的工作。

可以说,由于某些限制(不是服务器的资源限制),您的服务器只能处理有限数量的连接(基本上,每个连接将在单独的线程中处理,这在我们使用的服务器之间有所不同)。如果您的服务器可以处理的线程数多于连接数,并且如果您不想由于创建的异步工作而返回任何数据,则可以设计异步逻辑。因为您将创建一个新线程来处理请求的任务。

但是,如果您希望在响应中返回操作的结果,则没有什么不同。


use*_*900 5

您正在使用@Suspended与async结合使用,它仍在等待响应

@Suspended将暂停/暂停当前线程,直到获得响应

如果要在异步中获得更好的性能,请使用和编写其他具有即时响应的异步方法ExecutorServiceFuture

private ExecutorService executor;
private Future<String> futureResult;
@PostConstruct
public void onCreate() {
    this.executor = Executors.newSingleThreadExecutor();
}
@POST
public Response startTask() {
    futureResult = executor.submit(new ExpensiveTask());
    return Response.status(Status.ACCEPTED).build();
}
@GET
public Response getResult() throws ExecutionException, InterruptedException {
    if (futureResult != null && futureResult.isDone()) {
        return Response.status(Status.OK).entity(futureResult.get()).build();
    } else {
        return Response.status(Status.FORBIDDEN).entity("Try later").build();
    }
}
Run Code Online (Sandbox Code Playgroud)


sha*_*zin 0

我写这篇文章是根据我的个人经验,使用异步处理程序为斯里兰卡的前置出租车叫车服务编写促销引擎,该服务甚至与 Uber 并肩竞争。

当使用异步处理程序而不是同步处理程序时,它的可伸缩性、可用性和资源利用率比性能更高。

如果您使用同步处理程序,则最大并发请求数由可用于接受新连接的线程数定义,之后您的服务将不再接受请求。

就好像您使用异步处理程序一样,接受线程计数与您可以满足的并发请求数无关。因此,您的服务可以从 100 rps 扩展到 100 万 rps,并且可以具有高可用性。

如果您担心延迟和吞吐量,如果将非阻塞 API 与异步处理程序一起使用,则可以获得很好的改进。非阻塞套接字(NIO)、非阻塞存储(Mongo DB Reactive、Redis Reactive)、消息队列(Kafka、RabbitMQ)等。

  • 就好像您使用异步处理程序一样,接受线程计数与您可以满足的并发请求数无关。但在这种情况下,你需要另一个线程池来处理你的HTTP请求,它也不能是无限的。 (3认同)