Tomcat の同時接続数制御とSpring MVCの特定のコントローラに限った制御について

Tomcat の同時接続数制御は、基本的には サーバ全体の設定 に影響するものであり、特定のコントローラ に限って同時接続数を制御することは直接的にはできません。Tomcat の maxThreads や acceptCount といった設定は、Tomcat のサーバや特定のポートに対して適用され、そこで動作するすべてのアプリケーションやコントローラに影響を与えるグローバルな設定です。

ただし、Spring MVC や Servlet API で、アプリケーションレベルやコントローラ単位で制御するための手段を組み合わせることで、似たような動作を実現することは可能です。これには、Spring の `@Controller` や `@RestController` に対して、独自に同時接続数を制御する仕組みを作る方法があります。

## 1. スレッド数制限の手動実装
特定のコントローラだけで同時に処理できるリクエスト数を制限したい場合、Java の Semaphore を使って手動で制御する方法があります。Semaphore は、指定した数のスレッドのみが同時に特定の処理にアクセスできるように制御するクラスです。

実装例：特定のコントローラに対して同時接続数を制限する
```java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Semaphore;

@RestController
public class LimitedController {

    // ここで同時に許可するスレッド数を指定（例: 3）
    private static final Semaphore semaphore = new Semaphore(3);

    @GetMapping("/limited-endpoint")
    public String handleRequest() {
        boolean acquired = false;
        try {
            // セマフォを取得（空きがない場合は待機）
            semaphore.acquire();
            acquired = true;

            // リクエスト処理中の処理
            return "Request processed!";
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return "Error: Could not process request.";
        } finally {
            if (acquired) {
                // 処理が終わったらセマフォを解放
                semaphore.release();
            }
        }
    }
}
```

解説
Semaphore(3)：この設定により、同時に最大3つのスレッドだけが /limited-endpoint にアクセスできます。4つ目以降のリクエストは他のリクエストが完了するまで待機します。
acquire()：リソースが空いていれば取得し、最大数に達していれば待機します。
release()：リクエスト処理が終了した際にセマフォを解放し、次のリクエストを処理可能にします。

## 2. タイムアウトやエラーハンドリング

この Semaphore ベースの実装に追加して、一定時間待ってもリソースが解放されない場合にタイムアウトを発生させることや、同時接続数を超過した場合にエラーレスポンスを返すことも可能です。

タイムアウト付きの実装例

```java
import java.util.concurrent.TimeUnit;

@GetMapping("/limited-endpoint")
public String handleRequest() {
    boolean acquired = false;
    try {
        // 最大5秒間待機し、それでもセマフォが取得できなければタイムアウト
        if (semaphore.tryAcquire(5, TimeUnit.SECONDS)) {
            acquired = true;
            return "Request processed!";
        } else {
            return "Error: Too many concurrent requests.";
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        return "Error: Could not process request.";
    } finally {
        if (acquired) {
            semaphore.release();
        }
    }
}
```

解説
tryAcquire(5, TimeUnit.SECONDS)：5秒間だけセマフォを取得するのを待ち、それ以上待つとタイムアウトします。これにより、無限に待機することなく、適切なエラーメッセージを返すことが可能です。

## 3. Tomcat と組み合わせた同時接続数制御

Tomcat 側で設定されている maxThreads などのスレッド数制限は、全体の制御 になりますが、個別のコントローラレベルで Semaphore を使った同時接続数制御を行うことで、より細かな制御を行うことができます。

Tomcat 全体のスレッド数（maxThreads）はサーバレベルで設定。
特定のコントローラ単位の同時接続数制限は、Semaphore などを使った独自ロジックで設定。
これにより、アプリケーション全体に対する同時接続数の制御と、個別のコントローラに対する制御を両立させることが可能です。

まとめ
Tomcat の設定 (maxThreads など) はサーバ全体やポート単位で適用され、すべてのコントローラに影響します。
特定のコントローラに対してのみ同時接続数を制御したい場合、Java の Semaphore を使って個別に制御することが有効です。これにより、より細かい制御が可能です。
このように、Tomcat の設定に加えて、Spring MVC で独自の同時接続数制御を実装することができます。

### 4. 参考URL

https://stackoverflow.com/questions/35825352/semaphore-in-spring-mvc

https://www.baeldung.com/java-semaphore

https://medium.com/javarevisited/semaphore-in-java-6824fe663975