diff options
| author | eunhhu <[email protected]> | 2026-10-04 09:53:17 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-04 09:53:17 +0100 |
| commit | a90fdcd8932f1b876955c93dbbe13fbec8454007 (patch) | |
| tree | 496c392160c10086d67d1e436b0242f24d6f4d84 /docs/design/017-apps-on-one-host.md | |
| parent | 582294d084fced5bf5b3111f99a81cfb2422787e (diff) | |
| download | pure-a90fdcd8932f1b876955c93dbbe13fbec8454007.tar.gz pure-a90fdcd8932f1b876955c93dbbe13fbec8454007.zip | |
Say how apps start, stop and change on a running host, and what it must show (017, stage 3)
The --apps file is the host's shape: on SIGHUP the host reads it again
and starts the apps of new lines, stops those of lines gone, starts
again those whose line changed (states carried by name from the store)
and those stopped or uncertain. A request carries the module it was
resolved with, and is not applied under another (503 stopped); link
streams and local outlets look their input up again. Route
authentication (3b) is designed apart.
Diffstat (limited to 'docs/design/017-apps-on-one-host.md')
| -rw-r--r-- | docs/design/017-apps-on-one-host.md | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/docs/design/017-apps-on-one-host.md b/docs/design/017-apps-on-one-host.md index 3ffdc0f..f9ff765 100644 --- a/docs/design/017-apps-on-one-host.md +++ b/docs/design/017-apps-on-one-host.md @@ -1,7 +1,7 @@ # 017 — 한 호스트의 여러 앱: 차례, 예산, 실패 경계 작성일: 2026-10-01. 상태: 1·2단계와 2b 구현, 검사로 고정하고 쟀다([111](../research/111-apps-on-one-host.md), -[112](../research/112-sending-between-apps.md), [113](../research/113-one-sending-loop.md)). 3단계는 설계. +[112](../research/112-sending-between-apps.md), [113](../research/113-one-sending-loop.md)). 3단계는 착수 기준을 적었다(2026-10-04). [외부 리뷰 004](../outside-feedback/feedback-004.md)의 "구현 방향에 대한 평가" 셋째에서 시작한다. 작은 OS의 운영 모델( [007](007-execution-domains.md))을 Pure가 실제로 갖게 하는 단계다. @@ -231,6 +231,81 @@ counter apps/count.pmod stores/counter 모양과 이름으로 받는 모양, 메모리가 찬 앱에 보내는 것이 `kill -9`를 지나도 한 번씩 순서대로 간다. 커밋: Pure `8f75b32`(앱마다의 배선, 링크 포트 하나), `b7b86df`(안쪽 출구). +## 3단계: 앱의 수명 + +**구성 파일이 호스트의 모습이다.** `--apps FILE`은 시작할 때만 읽지 않는다. 호스트가 SIGHUP을 받으면 파일을 다시 읽고, 달리는 +앱들을 파일의 모습에 맞춘다. + +- 새 줄의 앱은 시작한다. 1단계의 시작과 같다(모듈 검증, 저장소, 배선, 실패하면 그 앱만 멈추고 까닭을 남긴다). +- 없어진 줄의 앱은 멈춘다(아래의 순서). 그 뒤로 그 경로는 404 `no_app`이다. +- 바뀐 줄의 앱은 멈추고 새 줄로 다시 시작한다. 모듈 파일의 내용, 저장소, 예산, 배선 가운데 하나라도 바뀐 줄이다. 상태는 + 저장소에서 이름으로 이어받는다(지금 다른 모듈로 다시 띄울 때와 같다, `server_upgrade`). +- 그대로인 줄의 앱은 건드리지 않는다. 멈춰 있거나(시작하지 못했거나) 불확실해진 앱만 다시 시작한다. 저장소에서 다시 연다. +- 다 맞추면 시작할 때와 같은 꼴의 줄 하나를 stdout에 낸다. 앱마다 상태와 까닭, 그리고 이번에 한 일(시작, 멈춤, 다시 시작)이다. +- 파일을 읽지 못하거나 틀린 줄이 있으면 아무것도 바꾸지 않고 까닭을 낸다. + +HTTP로 앱을 더하는 길을 두지 않는 까닭은 인증이다. 그 길은 경로의 인증(3b)을 먼저 요구한다. 신호는 프로세스의 주인만 보낼 수 있고, +파일은 호스트의 구성을 그대로 남긴다(다시 띄워도 같은 모습이다). 다시 읽기는 호스트의 스레드 하나(`pure-apps`)가 한다. 연결 +스레드와 실행 스레드는 기다리지 않는다. + +**멈추는 순서.** 앱 하나를 멈추는 것은 이렇다. + +1. 새 일을 받지 않는다. 그 앱의 경로는 503 `stopped`다. 링크와 안쪽 출구의 기록은 받지 않는다(보내는 쪽이 쥐고 다시 보낸다). +2. 소유자가 이미 받은 일을 다 적용하고, 저장하고, 답한다. +3. 그 앱의 보냄(전달선, 링크, 안쪽 출구)을 닫는다. 아직 가지 않은 것은 outbox에 남는다. 다른 앱에 가 있는 묶음은 돌아올 때까지 + 기다린다. +4. 저장소를 닫는다. 다른 프로세스가 열 수 있다. + +**모듈이 바뀌는 사이의 일.** 요청의 경로는 연결 스레드가 해석하고 적용은 실행 스레드가 한다. 그 사이에 모듈이 바뀌면 입력의 +번호와, JSON에서 이미 바꾼 페이로드의 배치가 새 모듈과 맞지 않는다. + +- 요청은 해석한 모듈을 들고 다닌다. 소유자는 지금의 모듈과 다른 모듈로 해석된 요청을 적용하지 않고 503 `stopped`로 답한다. + 클라이언트가 다시 보내면 새 모듈로 해석된다. 보기도 같다. 스냅숏의 모듈과 해석한 모듈이 다르면 503이다. +- 링크의 스트림은 받는 쪽 입력을 처음에 한 번 푼다(번호, 모양이 같은지, 이름으로 받는지). 앱이 다른 모듈로 다시 시작하면 + 링크를 받는 쪽에 그 앱의 스트림을 다시 풀게 한다. 그 사이에 넘어온 묶음은 받지 않는다(보내는 쪽이 다시 보낸다). +- 안쪽 출구는 받는 앱의 모듈이 바뀌면 그 입력을 이름으로 다시 찾는다(모양, 이름으로 받기). 찾지 못하면 쥐고 까닭을 남긴다. +- 모듈이 그대로면(예산이나 배선만 바뀌었거나 불확실해서 다시 연 것이면) 해석한 것이 그대로 맞다. 그대로 적용한다. + +**바뀐 모듈의 메모리.** 스냅숏과 연결 스레드의 리더가 모듈을 가리킨다. 그래서 바뀐 모듈은 호스트가 멈출 때까지 놓지 않는다. +한 번 바꿀 때 모듈 하나(18.7 KB와 모듈의 바이트)다. 잰다. + +**앱의 자리.** 앱의 자리는 호스트가 시작할 때 잡는다(`--app-slots N`, 기본 256, 처음의 앱 수보다 작지 않다). 자리는 이름과 +소유자, 그리고 연결 스레드마다의 리더다. 이름은 자리를 떠나지 않는다. 지운 앱의 이름을 다시 쓰면 그 자리로 간다. 연결 스레드가 +이름으로 자리를 찾는 동안 이름이 바뀌지 않기 때문이다. 쓰지 않은 자리는 손대지 않은 메모리라 상주하지 않는다. 자리가 다 차면 +새 앱은 까닭 "no slot"으로 멈춘다. + +**실행 스레드.** 달리는 앱이 실행 스레드보다 많아지면 CPU 수까지 하나씩 더한다(1단계의 규칙과 같다. 앱 수와 CPU 수 가운데 +작은 것이다). 줄이지는 않는다. 일 없는 실행 스레드는 잔다. + +**하지 않는 것.** + +- 끊김 없는 교체(새 모듈을 옆에서 띄우고 넘기기). 멈추고 다시 여는 동안 그 앱은 503을 답한다. 그 시간을 잰다. +- HTTP로 앱을 더하고 바꾸는 길. 경로의 인증(3b) 뒤에 따로 정한다. + +**3b: 경로의 인증.** 앱의 경로를 누가 부를 수 있는지다(CHECKPOINT의 남은 것). 3단계의 수명과 따로 설계한다. + +## 3단계의 착수 기준 + +- **바꿀 결정:** 달리는 호스트의 앱을 SIGHUP과 구성 파일로 더하고, 멈추고, 바꿀지다. 아래를 채우지 못하면 앱을 바꿀 때 호스트를 + 다시 띄운다(지금과 같다). +- **최소 확인**(`tests/check.py`의 `server_apps_lifecycle`): + - 한 호스트에서 앱을 더하면 그 앱이 바로 답한다. 지우면 그 경로가 404 `no_app`이고, 그 저장소를 다른 프로세스가 연다. 모듈을 + 바꾸면 상태를 이름으로 이어받는다. 그동안 다른 앱의 요청은 하나도 실패하지 않는다. + - 모듈을 바꾸는 동안에도 그 앱에 쓰기를 계속 보낸다. 200을 받은 쓰기는 모두 한 번씩 적용되고, 503 `stopped`를 받은 쓰기는 + 적용되지 않는다(합이 맞는다). + - 바뀌는 앱이 같은 호스트의 앱(안쪽 출구)과 다른 노드(링크)에서 받는 동안 입력의 번호가 바뀌는 모듈로 바꿔도, 보낸 것이 모두 한 + 번씩 순서대로 도착한다. 보내는 앱을 바꿔도 outbox의 것이 이어 간다. + - 저장소를 열지 못해 시작하지 못한 앱이, 고친 뒤의 SIGHUP에 시작한다. 틀린 줄이 있는 파일은 아무것도 바꾸지 않는다. + - 다시 읽은 뒤에 `kill -9`하고 다시 띄워도 상태와 앱들이 파일 그대로다. + - 1·2단계의 검사가 모두 초록이다. +- **통과 조건**(RAM의 Pi 5): + - 바꾸는 앱이 503을 답하는 시간(첫 503부터 첫 200까지)이 그 호스트를 다시 띄울 때 그 앱이 답하지 못하는 시간보다 짧다. 상태가 + 작은 앱(항목 1,000개)과 큰 앱(항목 100만 개)에서 각각 잰다. + - 한 앱을 거듭 바꾸는 동안 다른 앱(한 연결)의 p99가 바꾸지 않을 때의 1.5배를 넘지 않는다. + - 앱 하나의 호스트는 그대로다. TPC-C와 은행 질의를 전과 후 번갈아 재서 중앙값이 3% 넘게 느려지지 않고, 은행 질의의 명령 수가 + 1% 넘게 늘지 않는다. + - 바꿀 때마다 남는 메모리를 잰다(기준은 두지 않고 밝힌다). + ## 하지 않는 것 - 이벤트를 중간에 멈추고 다른 앱에 넘기는 선점. 이벤트는 원자적이고 끝까지 돈다. 그 대신 실행량 예산이 한 이벤트의 길이를, |
