Tomcat リソース設定(maxThreads,maxConnections,acceptCount)のちがい

maxThreads

  • リクエストを処理するスレッド数(workerスレッド)の上限
  • 1リクエストを処理するために1workerスレッドを消費する
  • コネクタ(HTTP1.1, AJPなど)ごとの上限
  • ただしスレッドプールをexecutorプロパティで指定した場合、この上限は無視される

maxConnections

  • 同時に受け付けるコネクション数の上限
  • workerスレッドに空きができるまで、リクエストは処理されない
  • Nioコネクタなら maxThreads < maxConnections が可能

acceptCount

  • 保留されている(Socket#accept()されない)ソケットの上限
  • 上限を超えたコネクションはTCPレベルで『connection refused』になる
  • ただしこの上限は実行環境へのヒントで、無視される可能性もある
  • maxConnectionsを超えたリクエストが来た場合、Acceptorスレッドを止めて待つ

図解

f:id:kimulla:20191201204046j:plain

動作確認

検証環境

  • Windows 10 Pro ver.1703
  • Java HotSpot(TM) 64-Bit Server VM ver.1.8.0_25
  • Apache Tomcat 8.5.23

検証コード

@RestController
@Slf4j
@SpringBootApplication
public class DemoxApplication {
  @Bean
  EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer() {
    return (container) -> {
      TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
      factory.addConnectorCustomizers(
          (connector) -> {
            Http11NioProtocol handler = (Http11NioProtocol) connector.getProtocolHandler();
            handler.setAcceptCount(1);
            handler.setMaxConnections(2);
            handler.setMaxThreads(1);
          }
      );
    };
  }

  @GetMapping
  public String hello() throws InterruptedException {
    log.info("wait a seconds");
    TimeUnit.SECONDS.sleep(5);
    return "I'm sorry, I'm late";
  }

  public static void main(String[] args) {
    SpringApplication.run(DemoxApplication.class);
  }
}

実行結果

  • コンソールログからmaxThreads分しか同時実行されない
  • maxConnections + acceptCountを超えたリクエストは『connection refused』されている

f:id:kimulla:20191201204100g:plain

参考