aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-04 12:58:53 +0100
committereunhhu <[email protected]>2026-10-04 12:58:53 +0100
commit21bf7dbf9a388fdb73e76118eeb8144b51f2481c (patch)
treefbd3ce8ebc0c8e1244ba95f1c63baac4fe4328dd /docs/research
parent9fd2e16b68e1a83e2605e8a9cbd9b6d04a4da2f6 (diff)
downloadpure-21bf7dbf9a388fdb73e76118eeb8144b51f2481c.tar.gz
pure-21bf7dbf9a388fdb73e76118eeb8144b51f2481c.zip
Say what an app's tokens cost (017 3b, research 116)
Requests to an app that checks tokens go 2.92% slower than to an open one on 64 keep-alive connections, 2.2% of it the head the token makes longer (an open app sent the same head is as slow); hashing every request on a new connection costs 0.91%. 031 measures the three in turns.
Diffstat (limited to 'docs/research')
-rw-r--r--docs/research/116-route-tokens.md58
1 files changed, 58 insertions, 0 deletions
diff --git a/docs/research/116-route-tokens.md b/docs/research/116-route-tokens.md
new file mode 100644
index 0000000..3a9028f
--- /dev/null
+++ b/docs/research/116-route-tokens.md
@@ -0,0 +1,58 @@
+# 116 — 앱의 경로에 토큰
+
+2026-10-04. [017](../design/017-apps-on-one-host.md)의 3b를 잰다. 기준은 구현하기 전에 017에 적어 커밋했다(`b15b5c6`).
+
+- 바꿀 결정: 앱의 경로에 토큰을 요구할지. 채우지 못하면 경로의 인증을 앞단에 맡긴다.
+- 통과 조건(RAM의 Pi 5): 토큰이 있는 앱의 보기(64연결, keep-alive)의 처리량 중앙값이 토큰 없는 같은 앱보다 3% 넘게 낮지 않다.
+ 요청마다 새 연결일 때 해시 하나의 값을 밝힌다.
+
+## 쉬운 말로
+
+- **통과했다(아슬아슬하게).** 토큰 파일이 있는 앱은 그 파일이 허락하는 토큰을 가진 요청만 받는다. 토큰을 확인하는 앱은 열린
+ 앱보다 2.92% 느리다. 그 가운데 2.2%는 확인이 아니라 요청의 머리가 토큰만큼(약 90바이트) 길어서다. 확인하지 않는 열린 앱에
+ 같은 머리를 보내도 그만큼 느리다. 확인 자체는 약 0.7%다.
+- 요청마다 새 연결이면 토큰을 매번 해시한다. 그래도 0.91%다. 연결을 맺는 일이 훨씬 크다.
+- 토큰 파일에는 토큰이 아니라 그 SHA-256이 있다. 해시는 호스트 안의 SHA-256(`serve/sha256.c`)이 한다. OpenSSL을 불러오지
+ 않는다.
+
+## 결과
+
+원시 결과와 명령은 [031-route-tokens](../../research/experiments/031-route-tokens/)에 있다(`tokens.py`).
+
+**방법.** 한 호스트(`--apps`, 연결 스레드 하나, 실행 스레드 둘, 저장소는 RAM, 코어 0–2)에 점수판 앱 둘: `open`(토큰 없음)과
+`held`(쓰기 토큰 하나를 허락하는 토큰 파일). 부하 도구(코어 3)가 `total` 보기를 10초 읽는다. 셋을 번갈아 다섯 라운드다. `open`,
+토큰을 붙인 채의 `open`(머리 길이만 같다), `held`다. keep-alive는 64연결(연결이 토큰을 한 번 해시한다), close는 16연결이다(요청마다
+새 연결이라 매번 해시한다).
+
+| 중앙값(초당 요청) | open | 토큰을 붙인 open | held |
+|---|---:|---:|---:|
+| keep-alive, 64연결 | 153,821 | 150,441 (−2.2%) | 149,336 (**−2.92%**) |
+| close, 16연결 | 22,868 | 22,713 (−0.68%) | 22,660 (−0.91%) |
+
+keep-alive에서 `held`는 다섯 라운드 모두 `open`보다 2–3% 낮았다. 흔들림이 아니라 값이다. 먼저 잰 두 방식만의 판에서도 −2.4%였고,
+토큰을 붙인 `open`을 따로 잰 판에서는 붙인 `open`과 `held`가 같았다(149,841 대 150,009). 확인의 몫은 0에서 0.7% 사이다.
+
+**검사**(`tests/check.py`의 `server_tokens`).
+- 토큰이 없으면 보기, 입력, 문서, 질의가 401이다(`WWW-Authenticate: Bearer`). 모르는 토큰도 401이다.
+- 권한마다:
+ - `read`는 보기, 질의, 문서 읽기만 된다. 입력과 문서 쓰기는 403이다.
+ - `write`는 모두 된다.
+ - `input=add`는 add에 보내기만 된다. 다른 입력과 보기는 403이다.
+- 거절된 쓰기는 아무것도 바꾸지 않는다.
+- SHA-256의 블록 경계에 걸친 길이(1, 55, 56, 63, 64, 65, 119, 200바이트)의 토큰이 모두 맞는다(Python `hashlib`의 다이제스트로 적었다).
+- 한 연결에서 같은 토큰, 다른 토큰, 다시 같은 토큰, 토큰 없음을 차례로 보내면 200, 200, 200, 401, 200, 401이다.
+- 토큰 파일을 바꾸고 SIGHUP을 보내면, 그동안 쉬지 않고 부른 요청이 하나도 503을 받지 않는다. 뺀 토큰은 401, 넣은 토큰은 200이다.
+- 토큰 파일이 아닌 파일이 오면 그 앱은 멈춘다(열려 있지 않는다). 고친 뒤의 SIGHUP에 다시 시작한다.
+- 이 호스트가 이름을 대는 보내는 쪽의 봉인된 전달은 토큰 없이 들어오고, 봉인 없는 전달은 토큰이 있어야 한다.
+- 앱 하나의 호스트는 `--tokens`로 같다.
+
+## 판정
+
+- **017의 3b는 들어간다.** 앱의 경로는 토큰 파일로 닫을 수 있다. 토큰 파일이 없는 앱은 지금처럼 열려 있다.
+- TLS는 들어가지 않는다. 호스트는 루프백에서 듣고, 밖으로는 TLS를 하는 앞단이 잇는다.
+
+## 다음
+
+- **머리를 읽는 값.** 비용의 대부분은 길어진 머리다. 머리의 끝을 바이트마다 찾는 일(`head_end`)과 머리의 이름을 차례로 견주는
+ 일은 모든 요청의 값이기도 하다. 줄이면 토큰이 있든 없든 빨라진다.
+- **HTTP로 앱을 더하고 바꾸는 길.** 이제 토큰이 있으니 열 수 있다(관리 권한의 토큰).