옵션과 기본값¶
가이드 홈 | 이전: 12. 운영 — 런타임 메트릭 · graceful drain · readiness | 다음: 14. 샘플 고르기 — 내 문제에 가까운 예제부터
다른 언어로 보기 — C++ · C#/.NET · Java · Kotlin · Node/TypeScript
이 장을 읽고 나면
무엇을 정할 수 있는지, 정하지 않으면 어떤 값으로 동작하는지, 시작한 뒤에 바꿀 수 있는 값이 무엇인지 안다.
옵션의 이름과 기본값은 지원 언어에서 같다. 언어마다 다른 것은 표기와 지정 방법이며 각 절의 탭이 그것을 보여준다. 대부분의 옵션은 지정하지 않아도 동작한다. 바꿀 이유가 생겼을 때 해당 줄의 기본값을 확인하고, 그전에는 그대로 사용한다.
1. 설정 위치와 적용 범위¶
같은 값이라도 어디에 지정하느냐에 따라 적용 범위와 바꿀 수 있는 시점이 달라진다.
| 위치 | 적용 범위 | 변경 시점 |
|---|---|---|
| 루트 옵션 | 이 process 전체의 기본값 | host 시작 전 |
| node builder | 그 MeshNode · channel · STREAM node 하나 | host 시작 전 |
| runtime option | 실행 중에 바꿀 수 있는 값 | 실행 중(§9) |
// Both sides must name the mesh identically, or they never see each other
// as peers. The routing id names this node; without it the Framework
// assigns a generated one, which a caller cannot type into a URL.
val mesh =
options
.addRouteMesh("game")
.listen("tcp://127.0.0.1:7601")
// The advertised endpoint must match the endpoint passed to
// connect(routingId, endpoint). Both use 127.0.0.1 here.
.setAdvertiseHost("127.0.0.1")
.setRoutingId(RoutingId.from("game-server-1"))
host가 시작된 뒤에 builder를 다시 호출하는 표면은 없다. 잘못된 조합은 첫 호출까지 미루지 않고 시작 단계에서 설정 오류로 끝난다.
2. 루트 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
| codec 등록 | payload 직렬화 형식 | 내장 JSON |
bindHost |
listener가 bind할 주소 | 127.0.0.1 |
advertiseHost |
상대에게 알릴 주소 | 지정 안 함 — non-wildcard bind 주소 또는 wildcard의 loopback |
defaultRequestTimeout |
request가 응답을 기다리는 상한 | 30초 |
sessionReplacementCallbackTimeout |
session 교체 callback이 끝나기를 기다리는 상한 | 30초 |
| stream compression | STREAM payload 압축 | LZ4 사용 |
worker MinThreads · maxThreads |
CPU worker 풀의 스레드 수 | 0 · 프로세서 수의 두 배 |
worker idleTimeout |
유휴 스레드를 정리하기까지의 시간 | 30초 |
applicationVersion · maintenanceWave |
rolling update가 비교할 버전과 점검 묶음 | 0 · 지정 안 함 |
| handler 탐색 · filter · metadata 정책 | 등록 대상과 전달 허용 key | 등록한 것만 |
| location store · relocation store | 위치 결정과 상태 이전 저장소 | 없으면 단일 node 구성 |
- bind 주소의 기본값은 loopback이다. 다른 host의 node나 client가 접속해야 한다면 bind 주소와 광고 주소를 각각 지정한다.
listenhost는 현재 process가 socket을 bind할 주소이고0.0.0.0은 모든 local interface에서 연결을 받는다.advertiseHost는 peer가 실제로 dial하고 Location Store에 게시할 주소다. wildcard bind에서는 단일 machine 예제처럼127.0.0.1을 지정한다. 여러 host, container, NAT, Kubernetes에서는 그 node에 도달 가능한 IP 또는 DNS를 지정하며, Kubernetes에서는 Pod IP 또는 pod별 DNS를 사용한다.advertiseHost를 생략하면 non-wildcard bind host를 광고하고, wildcard bind에는 같은 address family의 loopback을 사용한다. advertised host에는 wildcard를 지정할 수 없다. Channel 메시징의 언어별 mesh 등록 code block은 각 언어의 실제 option 표면을 보인다.- STREAM 압축은 켜진 상태로 시작한다. 끄려면 압축 설정에서 명시적으로 끈다.
- CPU worker 풀에는 대기열 상한이 없다. 유입을 제한하는 것은 Core HWM과 Application job queue 상한이다.
defaultRequestTimeout은0이하를 거부한다.
3. Core HWM과 Application job queue 상한¶
Core HWM은 ordinary queue가 보유한 byte를, Application job queue는 handler 시작을 기다리는 job 수를 host 전체에서 제한한다. 두 상한의 동작은 Backpressure — Core HWM과 Application job queue가 다룬다.
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
coreHwmMemoryLimitBytes |
Core budget 계산과 연결 수용 판정에 쓰는 양수 memory limit | 지정 안 함 |
coreHwmBudgetBytes |
profile 계산보다 우선하는 manual Core budget | 지정 안 함 |
CoreHwmProfile |
Core Auto-budget profile | Balanced |
ApplicationJobQueueProfile |
job 상한을 계산할 profile | Balanced |
maxQueuedApplicationJobs |
profile 계산을 대체하는 정확한 job 상한 | 지정 안 함 |
applicationJobQueuePauseThresholdPercent |
유입을 멈추는 사용률 | 80 |
applicationJobQueueResumeThresholdPercent |
유입을 다시 여는 사용률 | 60 |
Memory limit과 Core budget은 양수만 허용한다. Manual job 상한의 범위는 1..2,147,483,647이며
0은 무제한이 아니라 시작 단계 설정 오류다. 사용률은 각각 1..100과 0..99이고 다시 여는 값이
멈추는 값보다 작아야 한다. 두 profile은 같은 label을 쓰지만 독립된 값이며 Balanced는
프로세서당 128 job이다.
4. 진단 기록 설정¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
| 기록 수준 | off · errors · Normal · Detailed |
errors |
TraceSampleRate |
정상 흐름을 기록할 비율. 범위는 0.0..1.0 |
1.0 |
includeMessageSizes |
payload byte 크기를 함께 남길지 | 남기지 않음 |
handler가 없는 packet이 도착했을 때의 동작도 같은 자리에서 정한다. request는 보낸 쪽에 오류 응답을 보내고, send와 publish는 기록을 남기고 버린다. 응답 경로가 없는 send와 publish에는 오류 응답 동작을 지정할 수 없다. 이 설정은 C++에 없으며 기본 동작만 적용된다. 수준별로 무엇이 남는지는 모니터링이 다룬다.
5. MeshNode 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
listen |
다른 node가 접속할 자기 주소 | 지정해야 한다 |
bindHost · advertiseHost |
이 node만의 bind · 광고 주소 | 루트 값 |
RoutingId · routingIdPrefix |
이 node의 식별자 | 자동 생성 |
objectRole |
Spot · Actor 배치 참여 여부 | None |
placementWeight |
새 배치 대상으로 선택되는 비중. 범위는 0..10000 |
100 |
ActorLimit · spotLimit |
이 node가 동시에 담을 수 있는 상한 | 0 — 제한 없음 |
ActivationConcurrency |
동시에 진행할 cold activation 수 | 128 |
instanceSpotIdleTimeout |
유휴 Instance Spot을 정리하기까지의 시간 | 0 — 정리하지 않음 |
defaultRequestTimeout |
이 node에서 나가는 request의 상한 | 루트 값(30초) |
| peer connection | 수동으로 연결할 상대 | 없음 — location store가 찾아낸다 |
두 limit의 0은 제한 없음이고 양수는 1..2,147,483,647이다. ActivationConcurrency는 반대로
0을 거부한다 — object 수가 아니라 동시에 진행되는 활성화를 제한하는 값이기 때문이다.
6. 송신 대기와 socket 상한¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
Classic fanout publisher의 sendTimeout |
publish가 보낼 자리를 기다리는 상한 | 1초 |
receiveTimeout |
받는 방향의 대기 상한 | 지정 안 함 |
sendHighWaterMark · receiveHighWaterMark |
상대별로 보관할 byte. 0은 무제한 |
지정 안 함 — Core가 계산 |
Send는 capacity가 회복될 때까지 기다리며 시간 상한과 caller cancellation이 없다. 대기 중 route가 제거되면
Unavailable, socket이나 runtime이 종료되면 ShuttingDown으로 끝난다. Classic fanout publish만 publisher의
sendTimeout을 사용하며, 상한까지 capacity가 회복되지 않으면 DeadlineExceeded로 끝난다.
MeshNode 사이의 연결에는 message 크기 상한 설정이 없다 — 그 상한은 STREAM node와 ClientServer listener가 소유한다(Backpressure).
manual HWM을 지정하는 자리는 언어마다 다르다
방향별 byte 상한을 직접 지정하는 표면은 일부 언어에만 있고 C++에는 없다. 지정하지 않으면 Core가 physical queue를 근거로 계산하므로 값을 정하지 않는 것이 기본 구성이다. 실행 단위 하나의 mailbox를 message 수나 byte로 제한하는 설정은 어느 언어에서도 동작하지 않는다.
7. Location 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
ownerLeaseRenewInterval |
소유권을 갱신하는 주기 | 5초 |
ownerLeaseTtl |
갱신이 끊긴 소유권이 만료되는 시간 | 15초 |
ownerLeaseRenewTimeout |
갱신 시도 하나의 상한 | 3초 |
ownerLeaseFencingMargin |
만료 전에 권한을 반납하는 여유 | 5초 |
pollingInterval |
변경 알림이 없는 store를 다시 읽는 주기 | 1초 |
storeFailureGrace |
store 장애를 견디는 기간 | 30초 |
routeCacheMaxAge |
조회한 위치를 재사용하는 기간 | 15초 |
messageFollowDuration |
이전 owner가 새 owner로 message를 전달하는 기간 | 30초 |
sessionRelocationSealTimeout |
session 경로 갱신을 기다리는 상한 | 3초 |
RelocationPayloadChunkLimit |
relocation payload chunk 하나의 크기 상한 | 256 KiB |
RelocationInFlightPayloadBudget |
연결 하나가 동시에 전송하는 chunk byte 상한 | 16 MiB |
RelocationNodeInFlightPayloadBudget |
같은 상한의 node 전체 값 | 0 — 적용하지 않음 |
relocationCutoverWaitTimeout |
cutover를 기다리는 시간 | 1초 |
lease 값은 함께 움직인다. max(OwnerLeaseRenewInterval, OwnerLeaseRenewTimeout) + OwnerLeaseRenewTimeout이
OwnerLeaseTtl - OwnerLeaseFencingMargin보다 작아야 한다. 기본값은 8초와 10초로 이 관계를
만족한다. routeCacheMaxAge는 messageFollowDuration
보다 5초 이상 작아야 하고, 각각 0이면 경로 캐시와 message 전달을 끈다. 위치 결정과 이전
동작은 Location과 Relocation이 다룬다.
8. STREAM node 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
bind |
client가 접속할 주소 | 지정해야 한다 |
bindHost · advertiseHost |
bind · 광고 주소 | 루트 값 |
| session 등록 | 연결마다 만들 session 타입 | 지정해야 한다 |
maxMessageSize |
client가 보내는 message 하나의 byte 상한 | 64 KiB |
| TLS 설정 | 서버 인증서와 client 인증서 요구 여부 | 평문, client 인증서를 요구하지 않음 |
| Actor dispatch | 들어온 packet을 bind된 Actor로 전달 | 꺼져 있음 |
maxMessageSize는 client에서 server로 오는 방향에만 적용하고 0은 상한을 두지 않는다는 뜻이다.
크기를 넘긴 message는 handler에 일부도 전달하지 않고 server가 연결을 끊는다. Actor dispatch는
STREAM node마다 한 번만 활성화하며 두 번 호출하면 오류가 난다. 어느 mesh에서 Actor를 찾을지는
인자가 아니라 global ActorId가 정하므로 mesh 이름을 함께 지정하지 않는다. 등록 코드는
STREAM과 Session과 Actor 연결이 다룬다.
9. 실행 중 바꿀 수 있는 값¶
시작한 뒤에 바꿀 수 있는 값은 선택 비중이다. 나머지는 시작 시점에 확정된다.
| 값 | 무엇에 쓰나 |
|---|---|
| channel weight | 이 node가 새 request · send 대상으로 선택되는 비중 |
| placement weight | 새 Spot · Actor가 이 node에 배치되는 비중 |
// Weight is the one value this node can change while running. 0 keeps the
// socket open and finishes in-flight work, but other nodes stop choosing this
// one for new calls. 100 is the normal value.
//
// ZLinkRouteMeshRuntimeOptions is the Java surface, injected as a bean. There
// is no Kotlin projection of it, and weight() is a plain method pair rather
// than a getter/setter, so it is read and written by call and not by property.
@PostMapping("/admin/channels/{channel}/weight")
fun setWeight(@PathVariable channel: String, @RequestParam value: Int): WeightChanged {
mesh.channel(channel).weight(value)
return WeightChanged(channel, value)
}
data class WeightChanged(val channel: String, val weight: Int)
두 값의 범위는 0..10000이고 기본값은 100이다. 0으로 두면 새 배정만 멈춘다 — 이미 있는
object와 연결은 유지된다. 무중단 배포에서 이 node로 새 트래픽이 가지 않게 한 뒤 relocation을
시작하는 순서로 사용한다(운영과 lifecycle).
10. 반드시 지정하는 값¶
기본값이 없어 지정하지 않으면 시작이 실패하거나 의도한 동작이 나오지 않는 값이다.
| 값 | 빠뜨렸을 때 |
|---|---|
MeshNode의 listen 주소 |
시작 단계에서 설정 오류 |
| MeshNode의 channel 역할 또는 object 역할 하나 이상 | 시작 단계에서 설정 오류 |
STREAM node의 bind 주소와 session 타입 |
시작 단계에서 설정 오류 |
| Spot · Actor factory의 relocation 정책 정확히 하나 | 시작 단계에서 설정 오류 |
| 상태를 옮기는 factory나 Instance Spot이 있을 때의 relocation store | 시작 단계에서 설정 오류 |
| 여러 node를 사용할 때의 location store | 연결할 상대를 찾지 못한다 |
| 연결과 Actor 사이로 전달할 metadata key | 오류 없이 값만 전달되지 않는다 |
11. 자주 발생하는 문제¶
- 설정을 바꿨는데 반영되지 않는다 — 대부분의 옵션은 host 시작 시점에 확정된다. 실행 중 바꿀 수 있는 값은 §9에 정리되어 있다.
- 다른 host의 node가 접속하지 못한다 — bind 주소의 기본값은 loopback이다. bind 주소와 광고 주소를 각각 지정한다.
0으로 두었더니 memory가 계속 늘어난다 — byte 상한의0은 무제한이다. Core 계산에 맡기려면 값을 지정하지 않는다.- 소유권을 자꾸 잃는다 — 갱신 주기와 갱신 상한 중 큰 값에 갱신 상한을 더한 값이 유효 기간에서 여유를 뺀 값보다 크다.
- client가 보낸 큰 message에서 연결이 끊긴다 — STREAM의 크기 상한은 64 KiB다. 큰 payload를 받는 node라면 상한을 올린다.
- weight를
0으로 했더니 기존 연결도 끊길 것이라 예상했다 — weight는 새 배정만 막고 기존 object와 연결은 유지된다.
12. 관련 문서¶
- 상한이 무엇을 바꾸는지 — Backpressure
- 기록을 읽는 방법 — 모니터링
- weight로 트래픽을 빼는 절차 — 운영과 lifecycle
- 언어별 표면 이름 — 주요 타입 사용 색인