Skip to main content

Overriding client timeouts

Sometimes, the default timeouts used by the Armeria clients do not suit a particular scenario well. In these cases, you might want to override the timeout settings.

Using ClientBuilder

import java.time.Duration;

import com.linecorp.armeria.client.Clients;

int responseTimeout = 30;
int writeTimeout = 10;

HelloService.Iface client =
Clients.builder("tbinary+http://example.com/hello")
.responseTimeout(Duration.ofSeconds(responseTimeout))
.writeTimeout(Duration.ofSeconds(writeTimeout))
.build(HelloService.Iface.class);

Using WebClientRequestPreparation

You can override the properties defined in RequestOptions at request level using WebClient.prepare().

import com.linecorp.armeria.client.WebClient;

WebClient client = WebClient.of("http://example.com");
client.prepare()
.get("/hello")
.responseTimeout(Duration.ofSeconds(30))
.writeTimeout(Duration.ofSeconds(10)
.maxResponseLength(1024)
.execute();

Using RequestOptions

You can also create a RequestOptions to override the properties at request level. The created RequestOptions could be passed to WebClient.execute(HttpRequest,RequestOptions) with an HttpRequest.

import com.linecorp.armeria.client.RequestOptions;
import com.linecorp.armeria.common.HttpRequest;

HttpRequest req = HttpRequest.of(HttpMethod.GET, "/hello");
RequestOptions options =
RequestOptions.builder()
.responseTimeout(Duration.ofSeconds(30))
.writeTimeout(Duration.ofSeconds(10)
.maxResponseLength(1024)
.build();
client.execute(req, options);
tip

See Response properties to understand when the response timeout is scheduled.

Adjusting connection-level timeouts

You need to build a non-default ClientFactory using ClientFactoryBuilder to override the default connection-level timeouts such as connect timeout and idle timeout programmatically:

import com.linecorp.armeria.client.ClientFactory;

ClientFactory factory =
ClientFactory.builder()
// Increase the connect timeout from 3.2s to 10s.
.connectTimeout(Duration.ofSeconds(10))
// Shorten the idle connection timeout from 10s to 5s.
.idleTimeout(Duration.ofSeconds(5))
// Note that you can also adjust other connection-level
// settings such as enabling HTTP/1 request pipelining.
.useHttp1Pipelining(true)
.build();

Note that ClientFactory implements java.lang.AutoCloseable and thus needs to be closed when you terminate your application. On close(), ClientFactory will close all the connections it manages and abort any requests in progress.

Handling timeouts for streaming responses

For long-running streaming responses (e.g., gRPC server streaming, GraphQL subscriptions over WebSocket), the default response timeout applies to the entire duration of the stream—from the first message until the stream completes. This means that if your stream is expected to last longer than the configured response timeout, you must manually extend the timeout as messages are received.

You can extend the timeout dynamically using ClientRequestContext with TimeoutMode.EXTEND:

import com.linecorp.armeria.client.ClientRequestContext;
import com.linecorp.armeria.client.grpc.GrpcClients;
import com.linecorp.armeria.common.util.TimeoutMode;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

// gRPC streaming example
TestServiceStub client = GrpcClients.newClient(uri, TestServiceStub.class);

client.withDeadlineAfter(5, TimeUnit.SECONDS)
.streamingOutputCall(request, new StreamObserver<Response>() {
@Override
public void onNext(Response value) {
// Extend the timeout with each message received
ClientRequestContext ctx = ClientRequestContext.current();
ctx.setResponseTimeout(TimeoutMode.EXTEND, Duration.ofSeconds(5));
}

@Override
public void onError(Throwable t) {
// Handle error
}

@Override
public void onCompleted() {
// Stream completed
}
});

For blocking gRPC clients, you can capture the ClientRequestContext using Clients.newContextCaptor() and extend the timeout while iterating:

import com.linecorp.armeria.client.ClientRequestContext;
import com.linecorp.armeria.client.ClientRequestContextCaptor;
import com.linecorp.armeria.client.Clients;
import com.linecorp.armeria.common.util.TimeoutMode;

import java.time.Duration;
import java.util.Iterator;

TestServiceBlockingStub client = GrpcClients.newClient(uri, TestServiceBlockingStub.class);

Iterator<Response> iterator;
ClientRequestContext ctx;
try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
iterator = client.withDeadlineAfter(5, TimeUnit.SECONDS)
.streamingOutputCall(request);
ctx = captor.get();
}

while (iterator.hasNext()) {
Response response = iterator.next();
// Extend the timeout with each message received
ctx.setResponseTimeout(TimeoutMode.EXTEND, Duration.ofSeconds(5));
}

Alternatively, for streams with unpredictable duration, you can disable the timeout entirely:

// Disable response timeout for infinite streaming
WebClient client = WebClient.builder("http://example.com")
.responseTimeoutMillis(0)
.build();
tip

See Timeout control for more details on using TimeoutMode to dynamically adjust timeouts.

Understanding timeout origins

Timeouts can originate from either the client or server side, and understanding this is crucial for debugging timeout-related issues. For detailed information about how timeouts and cancellations propagate between clients and servers, see Understanding timeout and cancellation origins.

Using JVM system properties

You can override the default client timeouts by specifying the following JVM system properties if you do not prefer setting it programmatically:

  • -Dcom.linecorp.armeria.defaultClientIdleTimeoutMillis=<integer>
    • the default client-side idle timeout of a connection for keep-alive in milliseconds. Default: 10000
  • -Dcom.linecorp.armeria.defaultConnectTimeoutMillis=<integer>
    • the default client-side timeout of a socket connection attempt in milliseconds. Default: 3200
  • -Dcom.linecorp.armeria.defaultWriteTimeoutMillis=<integer>
    • the default client-side timeout of a socket write attempt in milliseconds. Default: 1000
  • -Dcom.linecorp.armeria.defaultResponseTimeoutMillis=<integer>
    • the default client-side timeout of a response in milliseconds. Default: 15000
warning

The JVM system properties have effect only when you did not specify them programmatically. See Flags for the complete list of JVM system properties in Armeria.

Like Armeria?
Star us ⭐️

×