Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/multitenancy-isolation/case/case-tenant-pools-summed-past-the-server-ceiling.md
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

88 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
kind: CASE
slug: tenant-pools-summed-past-the-server-ceiling
title: tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다
topic: multitenancy-isolation
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: case:tenant-pools-summed-past-the-server-ceiling
evidenceCapturedOn: 2026-09-01
assets:
- key: tenant-pools-summed-past-the-server-ceiling
file: ../../../final/evidence/rendered/tenant-pools-summed-past-the-server-ceiling.svg
evidence:
- ../../../final/evidence/raw/tenant-pools-summed-past-the-server-ceiling.txt
source:
- 원본 분석 절은 analysis/05 §13.2 이다.
---
# tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다
테넌트별 데이터베이스 전략은 특정한 방식으로 실패한다. 각 테넌트의 풀은 개별적으로 합리적이고 그 합이 아니다. 실패는 유휴 상태이던 테넌트를 포함해 모든 테넌트에 동시에 도착한다.
## 관계
- **REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약**
같은 자원 계산의 다른 축이다.
- **네 가지 멀티테넌시 전략과 각각의 격리 경계**
이 전략의 실패 모드다.
- **데드라인은 호출 예산에서 시작해 세 단계로 좁힌다**
풀 획득이 예산의 일부라는 점에서 연결된다.
## 문제
테넌트별 데이터베이스는 커넥션 자체가 격리 경계다. 각 테넌트가 자기 풀을 갖는다.
풀 크기는 테넌트마다 정한다. 그 값은 개별적으로는 합리적이다.
## 결론
합이 서버 상한을 넘는다.
테넌트 50 개에 각각 커넥션 10 개면 500 이다. 서버의 최대 커넥션이 100 이면 400 이 거절된다.
그리고 그 거절은 한 테넌트에만 오지 않는다. 유휴 상태이던 테넌트를 포함해 모든 테넌트에 동시에 커넥션 거절로 도착한다. 서버의 상한은 전역이기 때문이다.
그래서 예산 타입이 두 상한을 갖는다. 풀 개수와 커넥션 총합이다.
둘 다 필요한 이유가 javadoc 에 적혀 있다. 풀 개수만으로는 풀 크기 차이를 무시하고, 커넥션 총합만으로는 각자 스레드와 모니터링을 가진 무한한 수의 작은 풀을 허용한다.
다만 예산 자체에 결함이 있다. 새 풀의 크기를 계산에 넣지 않아 상한을 넘길 수 있다.
## 검증 환경
확인 방식 : 예산 타입의 두 상한과 javadoc 확인
소스 수정 : x
## 재현 조건
1. 테넌트 풀 예산 타입의 두 상한을 확인한다.
2. 각 상한이 필요한 이유를 javadoc 에서 읽는다.
3. 새 풀을 승인할 때 그 풀의 크기가 계산에 들어가는지 확인한다.
## 본문
<!-- body:start -->
database-per-tenant는 특정한 방식으로 실패한다 — 각 tenant의 풀은 개별적으로 합리적이고 **그 합이 아니다.** 50 tenant × 10 커넥션 = `max_connections`가 100인 서버에 500 커넥션이고, 실패는 **idle이던 것 포함 모든 tenant에 동시에** connection refusal로 도착한다.
## TenantPoolBudget 참조 위치
:::evidence key="tenant-pools-summed-past-the-server-ceiling" alt="코드베이스에서 TenantPoolBudget 를 검색한 출력 4줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="TenantPoolBudget 코드베이스 검색 — 4줄 · exit 0" zoom="true"
:::
## ceiling 이 둘인 이유
pool count만으로는 풀 크기 차이를 무시하고, connection total만으로는 각자 스레드와 모니터링을 가진 무한한 수의 작은 풀을 허용한다.
## 예산이 새 pool 크기를 계산하지 않는다
`analysis/05` §98이 기록하듯 그래서 ceiling을 넘길 수 있다.
## 확인하지 못한 것
다중 테넌트 풀을 실제로 세워 상한 초과를 재현하지 않았다. 이 전략은 실험 플래그 뒤에 있다.
<!-- body:end -->