Production checklist
You may want to consider the following options before putting your Armeria application into production.
Specify the maximum number of accepted connections. The default is unbounded.
import com.linecorp.armeria.server.Server; import com.linecorp.armeria.server.ServerBuilder; ServerBuilder sb = Server.builder(); sb.maxNumConnections(500);
Specify an alternative
blockingTaskExecutor
based on expected workload if your server has a service that uses it, such asTomcatService
,JettyService
andTHttpService
with synchronous service implementation. The default is a simpleScheduledThreadPoolExecutor
with maximum 200 threads, provided byCommonPools
.import com.linecorp.armeria.server.ServerBuilder; ServerBuilder sb = Server.builder(); sb.blockingTaskExecutor(myScheduledExecutorService);
Specify the default limits of an HTTP request or response.
import java.time.Duration; import com.linecorp.armeria.client.ClientBuilder; import com.linecorp.armeria.server.ServerBuilder; // Server-side ServerBuilder sb = Server.builder(); sb.maxRequestLength(1048576); // bytes (default: 10 MiB) sb.requestTimeout(Duration.ofSeconds(7)); // (default: 10 seconds) // Client-side ClientBuilder cb = Clients.builder(...); // or WebClient.builder(...) cb.maxResponseLength(1048576); // bytes (default: 10 MiB) cb.responseTimeout(Duration.ofSeconds(10)); // (default: 15 seconds)
Decorate your services with
ThrottlingService
which lets you fail the incoming requests based on a policy, such as 'fail if the rate of requests exceed a certain threshold.import com.linecorp.armeria.server.throttling.ThrottlingService; import com.linecorp.armeria.server.throttling.ThrottlingStrategy; ServerBuilder sb = Server.builder(); sb.service("/my_service", // Allow up to 1000 requests/sec. myService.decorate(ThrottlingService.newDecorator( ThrottlingStrategy.rateLimiting(1000.0))));
Decorate your clients with
RetryingClient
. See Automatic retry.Decorate your clients with
CircuitBreakerClient
. See Circuit breaker.
Tune the socket options.
import com.linecorp.armeria.client.ClientBuilder; import com.linecorp.armeria.client.ClientFactory; import com.linecorp.armeria.client.ClientFactoryBuilder; import com.linecorp.armeria.server.ServerBuilder; import io.netty.channel.ChannelOption; // Server-side ServerBuilder sb = Server.builder(); sb.channelOption(ChannelOption.SO_BACKLOG, ...); sb.channelOption(ChannelOption.SO_REUSEADDR, ...); sb.childChannelOption(ChannelOption.SO_SNDBUF, ...); sb.childChannelOption(ChannelOption.SO_RCVBUF, ...); // Client-side ClientFactoryBuilder cfb = ClientFactory.builder(); cfb.channelOption(ChannelOption.SO_REUSEADDR, ...); cfb.channelOption(ChannelOption.SO_SNDBUF, ...); cfb.channelOption(ChannelOption.SO_RCVBUF, ...); ClientFactory cf = cfb.build(); ClientBuilder cb = Clients.builder(...); cb.factory(cf);
Consider increasing
ClientFactoryBuilder.maxNumEventLoopsPerEndpoint()
andClientFactoryBuilder.maxNumEventLoopsPerHttp1Endpoint()
when a client needs to send a large number of requests to a specific endpoint. The client will assign more CPU resources and create more connections by increasing the number of event loops up to the quantity inClientFactory.eventLoopGroup()
.import com.linecorp.armeria.client.Clients; import com.linecorp.armeria.client.ClientBuilder; import com.linecorp.armeria.client.ClientFactory; import com.linecorp.armeria.client.ClientFactoryBuilder; ClientFactoryBuilder cfb = ClientFactory.builder(); cfb.maxNumEventLoopsPerEndpoint(16); // default: 1 cfb.maxNumEventLoopsPerHttp1Endpoint(16); // default: 1 ClientFactory cf = cfb.build(); ClientBuilder cb = Clients.builder(...); cb.factory(cf);