Expected Behavior
invokeMethod sends requests asynchronously and parallel. The number of connections, threads etc can be configured. The performance should match calling the api endpoint directly.
Actual Behavior
We have started investigating as we noticed that under load, requests are processed almost sequentially, leading to very long processing time if the target method takes long time to complete.
There is no possibility to control the underlying http client or configure anything in order to mitigate this problem, which was only solved by increasing the number of instances.
Comparing to calling the rest endpoint directly, the throughput of invokeMethod is about 16 times slower.
Steps to Reproduce the Problem
Please find a modified version of the invoke example from the sdk. Request processing at the server side is 1 second to demonstrate the effect. HTTP Client call is commented out, please uncomment it and comment the invoke method for a comparison.
Also find modified logs of both executions, with the httpclient and with dapr invokeMethod.
As you can see, execution with the httpclient takes around 1 second for all 50 requests while with dapr invoke it takes around 16 seconds.
with-dapr-invoke.txt
with-http-client.txt
DemoServiceController.java
@PostMapping(path = "/say")
public Mono<String> handleMethod(@RequestBody(required = false) byte[] body,
@RequestHeader Map<String, String> headers) {
return Mono.fromSupplier(() -> {
try {
String message = body == null ? "" : new String(body, StandardCharsets.UTF_8);
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Handles the request by printing message.
System.out.println(String.format("%s server request received", Instant.now().toEpochMilli()));
Thread.sleep(1000);
System.out.println(String.format("%s server request done", Instant.now().toEpochMilli()));
return message + " received";
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
DemoServiceController.java
public static void main(String[] args) throws Exception {
var executor = Executors.newFixedThreadPool(50);
try (DaprClient client = (new DaprClientBuilder()).build()) {
for (var i = 0; i < 50; i++) {
final String msg = "" + i;
final Integer key = i;
executor.execute(() -> {
var timestamp = Instant.now().toEpochMilli();
// use invokeMethod
System.out.println(String.format("%d client invoke started", timestamp));
client.invokeMethod(SERVICE_APP_ID, "say", "" + msg, HttpExtension.POST, null,
byte[].class).block();
// use http client directly
// System.out.println(String.format("%d http client request started", timestamp));
// HttpClient httpClient = HttpClient.newHttpClient();
// HttpRequest request = HttpRequest.newBuilder()
// .POST(HttpRequest.BodyPublishers.ofString("message"))
// .uri(URI.create("http://localhost:3000/say"))
// .build();
// httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
// .thenApply(HttpResponse::body)
// .thenAccept(System.out::println)
// .join();
// System.out.println(String.format("%d client http request done", timestamp));
timestamp = Instant.now().toEpochMilli();
System.out.println(String.format("%d client invoke done", timestamp));
});
}
}
}
add this to the application properties:
server.tomcat.threads.max=400
Release Note
RELEASE NOTE:
Expected Behavior
invokeMethod sends requests asynchronously and parallel. The number of connections, threads etc can be configured. The performance should match calling the api endpoint directly.
Actual Behavior
We have started investigating as we noticed that under load, requests are processed almost sequentially, leading to very long processing time if the target method takes long time to complete.
There is no possibility to control the underlying http client or configure anything in order to mitigate this problem, which was only solved by increasing the number of instances.
Comparing to calling the rest endpoint directly, the throughput of invokeMethod is about 16 times slower.
Steps to Reproduce the Problem
Please find a modified version of the invoke example from the sdk. Request processing at the server side is 1 second to demonstrate the effect. HTTP Client call is commented out, please uncomment it and comment the invoke method for a comparison.
Also find modified logs of both executions, with the httpclient and with dapr invokeMethod.
As you can see, execution with the httpclient takes around 1 second for all 50 requests while with dapr invoke it takes around 16 seconds.
with-dapr-invoke.txt
with-http-client.txt
DemoServiceController.java
DemoServiceController.java
add this to the application properties:
server.tomcat.threads.max=400Release Note
RELEASE NOTE: