SIerだけど技術やりたいブログ

6年目のSIerのブログです

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

リファレンスだけを読んでも違いがわからなかったので、調べた。

Apache Tomcat 8 Configuration Reference (8.5.24) - The HTTP Connector

maxThreads

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

maxConnections

  • 同時に受け付けるコネクション数の上限
  • workerスレッドに空きがなければリクエストは処理されない
  • Nioコネクタなら maxThreads < maxConnections が可能
    • デフォルトは maxThreads=200, maxConnections=10000
    • HTTP Keep AliveごとにThreadを利用する必要がないから
    • ここらへんは昔に調べた

kimulla.hatenablog.com

acceptCount

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

図にしてみた。
f:id:kimulla:20171230100804j:plain

動作確認

以下の環境で動作確認した。

@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:20171230112918g:plain