简体   繁体   English

通过toStrict()将HttpEntity转换为String后导致延迟的原因

[英]What is causing the delay after converting HttpEntity to String via toStrict()

I'm using akka-http for a web application that has a quite short response time target. 我正在使用akka-http作为响应时间非常短的Web应用程序。 I use the routing DSLs completeWithFuture method with a chain of CompletableFuture s. 我使用路由DSLs completeWithFuture方法和CompletableFuture链。

I noticed that, when chaining every future using the XXXasync variant of the CompletionStage methods and passing the same executor, the thread used for processing the stage can change arbitrarily, causing a higher response time for some requests in case that all threads of the specified executor are used. 我注意到,当使用CompletionStage方法的XXXasync变体链接每个未来并传递相同的执行程序时,用于处理阶段的线程可以任意更改,从而在指定执行程序的所有线程的情况下为某些请求引起更高的响应时间使用。 So I passed my custom executor to the first CompletableFuture and chained all following stages with normal variant, in order to use the same thread for them. 因此,我将自定义执行程序传递给第一个CompletableFuture,并使用普通变量链接所有后续阶段,以便为它们使用相同的线程。

Problem : One stage does the conversion of the HttpEntity to a String via HttpEntity.toStrict() and that method uses a thread from akka.actor.default-dispatcher . 问题 :一个阶段通过HttpEntity.toStrict()将HttpEntity转换为String,该方法使用来自akka.actor.default-dispatcher的线程。 With increasing workload there are more and more requests that exceed the required response time at the beginning of the next stage, despite passing a timeout to toStrict that is way lower than the targeted response time and seeing no timeout exceptions. 随着工作负载的增加,越来越多的请求超过了下一阶段开始时所需的响应时间,尽管将超时时间传递给toStrict ,这超出了目标响应时间并且没有看到超时异常。

Simplified Code : 简化代码

private Route handleRequest(final HttpRequest request) {
    return completeWithFuture(CompletableFuture.runAsync(() -> preprocessing(), systemDispatcher) // Dispatcher 1
            .thenCompose((preprocessingResult) -> // please ignore that preprocessingResult is not used in that simplified version
            entityToString(request.entity()).thenApply((requestString) -> generateResponse(requestString))));
}

public CompletionStage<String> entityToString(final HttpEntity entity) {
        long start = System.nanoTime();
        return entity.toStrict(bodyReadTimeoutMillis, materializer).thenApplyAsync((final Strict strict) -> {
            System.out.println(start-System.nanoTime()); // varies between <1ms and >500ms
            return strict.getData().utf8String();
        }, systemDispatcher); // Dispatcher 2
    }

So my guess is that the switch from a thread of my custom executor to one of akkas default actor dispatcher thread and back is causing the problem. 所以我的猜测是从我的自定义执行程序的一个线程切换到一个akkas默认的actor调度程序线程并返回导致问题。

Questions : Is there another explanation for the delay in my entityToString method? 问题 :我的entityToString方法有延迟的另一种解释吗? Is there a way to achieve the same as toStrict, ie getting the whole possibly chunked message body as string while avoiding to switch threads multiple times? 有没有办法实现与toStrict相同,即将整个可能的分块消息体作为字符串,同时避免多次切换线程?

Please note that I need the timeout functionality of the toStrict method to abort processing of slow POST requests. 请注意,我需要toStrict方法的超时功能来中止慢速POST请求的处理。

UPDATE UPDATE

Thinking about it for the last days, I believe that it is not possible to achieve a non-blocking read, that akka guarantees, without switching threads. 考虑到它的最后几天,我相信不可能实现非阻塞读取,akka保证,而不切换线程。 So the real problem is the noticeably high delay probably caused by the scheduling after toStrict . 所以真正的问题是可能由于在toStrict之后的调度引起的明显高的延迟。

I tried to use different dispatchers (see the comments Dispatcher 1 / Dispatcher 2 in the code above) and logged the inhabitants count of Dispatcher 2 in the case the delay exceeds 50ms. 我尝试使用不同的调度程序(请参阅上面代码中的注释调度程序1 / 调度程序2 )并在延迟超过50毫秒的情况下记录调度程序2的居民数。 I can not find a proper documentation but I assume this is the number of scheduled tasks. 我找不到合适的文档,但我认为这是计划任务的数量。 I ran apache bench with 10000 requests, 200 concurrent connections and got 55 times a delay exceeding 50ms. 我运行apache bench有10000个请求,200个并发连接,并且有55次延迟超过50ms。 The output shows a maximum of 80 inhabitants. 输出显示最多80个居民。

I ran that test on Amazons m3.2xlarge instance (8 vCPU, 30GB RAM, Ubuntu 16.04), no other processes consuming any noticeable amount of cpu). 我在Amazons m3.2xlarge实例(8个vCPU,30GB RAM,Ubuntu 16.04)上运行该测试,没有其他进程消耗任何明显的cpu量)。 The dispatchers are of type fork-join-executor with parallelism-factor = 1. 调度程序的类型为fork-join-executor ,parallelism-factor = 1。

Real traffic with a much more variable number of concurrent requests causes an increasing rate of requests that exceed the limit (up to 50%). 具有更多可变并发请求数量的实际流量会导致超出限制的请求率增加(最多50%)。

The average time for processing a request is below 1ms. 处理请求的平均时间低于1毫秒。 What is causing that infrequent delay after toStrict and how to avoid it? 是什么导致了严重后的不频繁延迟以及如何避免它?

You can try get the entity content using akka-streams, and achieve timeout requirement in a different way instead of entity read. 您可以尝试使用akka-streams获取实体内容,并以不同的方式而不是实体读取来实现超时要求。

entity.getDataBytes().runFold(ByteString.empty(), ByteString::concat, materializer)
.thenCompose(r -> r.utf8String());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在httpclient中,将HttpEntity转换为String的最优雅/正确的方法是什么? - In httpclient what is the most elegant/correct way to turn HttpEntity to a String? 从 DescribeSObjectResult 转换为 JsonArray(或 HttpEntity) - Converting from DescribeSObjectResult to JsonArray (or to HttpEntity) Spring中ResponseEntity和HttpEntity有什么区别? - What's the difference between ResponseEntity and HttpEntity in Spring? 将HttpEntity解码为android字符串 - 编码问题 - Decoding HttpEntity into android string - encoding issue Spring RestTemplate POST请求不适用于HttpEntity <String> - Spring RestTemplate POST request is not working with HttpEntity<String> 通过蓝牙持续不断地发送字符串消息 - Send a string message continously with delay via Bluetooth HttpEntity <String> request = new HttpEntity <String> (); 我如何在java中模拟它 - HttpEntity<String> request = new HttpEntity<String>( ); How do I mock this in java 字符串转double后的问题 - Problems after converting string to double Firebase数据库RecyclerView中的一个片段导致将数据库转换为字符串时出错 - Firebase database RecyclerView in a fragment causing Error in converting database to String 通过Rest将String返回方法转换为jSON - Converting String return method to jSON via Rest
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM