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 as TomcatService, JettyService and THttpService with synchronous service implementation. The default is a simple ScheduledThreadPoolExecutor with maximum 200 threads, provided by CommonPools.

    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() and ClientFactoryBuilder.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 in ClientFactory.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);