옵션과 기본값¶
가이드 홈 | 이전: 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.
zlink::routing_id_t routing_id = zlink::routing_id_t::from ("game-server-1");
auto mesh = options.add_route_mesh ("game")
.listen ("tcp://127.0.0.1:7401")
.set_routing_id (routing_id)
// Publish the same loopback address that this node listens on.
.set_advertise_host ("127.0.0.1");
host가 시작된 뒤에 builder를 다시 호출하는 표면은 없다. 잘못된 조합은 첫 호출까지 미루지 않고 시작 단계에서 설정 오류로 끝난다.
2. 루트 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
| codec 등록 | payload 직렬화 형식 | 내장 JSON |
bind_host |
listener가 bind할 주소 | 127.0.0.1 |
advertise_host |
상대에게 알릴 주소 | 지정 안 함 — non-wildcard bind 주소 또는 wildcard의 loopback |
default_request_timeout |
request가 응답을 기다리는 상한 | 30초 |
session_replacement_callback_timeout |
session 교체 callback이 끝나기를 기다리는 상한 | 30초 |
| stream compression | STREAM payload 압축 | LZ4 사용 |
worker MinThreads · max_threads |
CPU worker 풀의 스레드 수 | 0 · 프로세서 수의 두 배 |
worker idle_timeout |
유휴 스레드를 정리하기까지의 시간 | 30초 |
application_version · maintenance_wave |
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에서 연결을 받는다.advertise_host는 peer가 실제로 dial하고 Location Store에 게시할 주소다. wildcard bind에서는 단일 machine 예제처럼127.0.0.1을 지정한다. 여러 host, container, NAT, Kubernetes에서는 그 node에 도달 가능한 IP 또는 DNS를 지정하며, Kubernetes에서는 Pod IP 또는 pod별 DNS를 사용한다.advertise_host를 생략하면 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 상한이다.
default_request_timeout은0이하를 거부한다.
3. Core HWM과 Application job queue 상한¶
Core HWM은 ordinary queue가 보유한 byte를, Application job queue는 handler 시작을 기다리는 job 수를 host 전체에서 제한한다. 두 상한의 동작은 Backpressure — Core HWM과 Application job queue가 다룬다.
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
core_hwm_memory_limit_bytes |
Core budget 계산과 연결 수용 판정에 쓰는 양수 memory limit | 지정 안 함 |
core_hwm_budget_bytes |
profile 계산보다 우선하는 manual Core budget | 지정 안 함 |
CoreHwmProfile |
Core Auto-budget profile | Balanced |
ApplicationJobQueueProfile |
job 상한을 계산할 profile | Balanced |
max_queued_application_jobs |
profile 계산을 대체하는 정확한 job 상한 | 지정 안 함 |
set_application_job_queue_pause_threshold_percent |
유입을 멈추는 사용률 | 80 |
set_application_job_queue_resume_threshold_percent |
유입을 다시 여는 사용률 | 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 |
include_message_sizes |
payload byte 크기를 함께 남길지 | 남기지 않음 |
handler가 없는 packet이 도착했을 때의 동작도 같은 자리에서 정한다. request는 보낸 쪽에 오류 응답을 보내고, send와 publish는 기록을 남기고 버린다. 응답 경로가 없는 send와 publish에는 오류 응답 동작을 지정할 수 없다. 이 설정은 C++에 없으며 기본 동작만 적용된다. 수준별로 무엇이 남는지는 모니터링이 다룬다.
5. MeshNode 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
listen |
다른 node가 접속할 자기 주소 | 지정해야 한다 |
bind_host · advertise_host |
이 node만의 bind · 광고 주소 | 루트 값 |
RoutingId · RoutingIdPrefix |
이 node의 식별자 | 자동 생성 |
object_role |
Spot · Actor 배치 참여 여부 | None |
placement_weight |
새 배치 대상으로 선택되는 비중. 범위는 0..10000 |
100 |
actor_limit · spot_limit |
이 node가 동시에 담을 수 있는 상한 | 0 — 제한 없음 |
ActivationConcurrency |
동시에 진행할 cold activation 수 | 128 |
instance_spot_idle_timeout |
유휴 Instance Spot을 정리하기까지의 시간 | 0 — 정리하지 않음 |
default_request_timeout |
이 node에서 나가는 request의 상한 | 루트 값(30초) |
| peer connection | 수동으로 연결할 상대 | 없음 — location store가 찾아낸다 |
두 limit의 0은 제한 없음이고 양수는 1..2,147,483,647이다. ActivationConcurrency는 반대로
0을 거부한다 — object 수가 아니라 동시에 진행되는 활성화를 제한하는 값이기 때문이다.
6. 송신 대기와 socket 상한¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
Classic fanout publisher의 send_timeout |
publish가 보낼 자리를 기다리는 상한 | 1초 |
receive_timeout |
받는 방향의 대기 상한 | 지정 안 함 |
SendHighWaterMark · ReceiveHighWaterMark |
상대별로 보관할 byte. 0은 무제한 |
지정 안 함 — Core가 계산 |
Send는 capacity가 회복될 때까지 기다리며 시간 상한과 caller cancellation이 없다. 대기 중 route가 제거되면
Unavailable, socket이나 runtime이 종료되면 ShuttingDown으로 끝난다. Classic fanout publish만 publisher의
send_timeout을 사용하며, 상한까지 capacity가 회복되지 않으면 DeadlineExceeded로 끝난다.
MeshNode 사이의 연결에는 message 크기 상한 설정이 없다 — 그 상한은 STREAM node와 ClientServer listener가 소유한다(Backpressure).
manual HWM을 지정하는 자리는 언어마다 다르다
방향별 byte 상한을 직접 지정하는 표면은 일부 언어에만 있고 C++에는 없다. 지정하지 않으면 Core가 physical queue를 근거로 계산하므로 값을 정하지 않는 것이 기본 구성이다. 실행 단위 하나의 mailbox를 message 수나 byte로 제한하는 설정은 어느 언어에서도 동작하지 않는다.
7. Location 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
owner_lease_renew_interval |
소유권을 갱신하는 주기 | 5초 |
owner_lease_ttl |
갱신이 끊긴 소유권이 만료되는 시간 | 15초 |
owner_lease_renew_timeout |
갱신 시도 하나의 상한 | 3초 |
owner_lease_fencing_margin |
만료 전에 권한을 반납하는 여유 | 5초 |
polling_interval |
변경 알림이 없는 store를 다시 읽는 주기 | 1초 |
store_failure_grace |
store 장애를 견디는 기간 | 30초 |
route_cache_max_age |
조회한 위치를 재사용하는 기간 | 15초 |
message_follow_duration |
이전 owner가 새 owner로 message를 전달하는 기간 | 30초 |
session_relocation_seal_timeout |
session 경로 갱신을 기다리는 상한 | 3초 |
RelocationPayloadChunkLimit |
relocation payload chunk 하나의 크기 상한 | 256 KiB |
RelocationInFlightPayloadBudget |
연결 하나가 동시에 전송하는 chunk byte 상한 | 16 MiB |
RelocationNodeInFlightPayloadBudget |
같은 상한의 node 전체 값 | 0 — 적용하지 않음 |
relocation_cutover_wait_timeout |
cutover를 기다리는 시간 | 1초 |
lease 값은 함께 움직인다. max(OwnerLeaseRenewInterval, OwnerLeaseRenewTimeout) + OwnerLeaseRenewTimeout이
OwnerLeaseTtl - OwnerLeaseFencingMargin보다 작아야 한다. 기본값은 8초와 10초로 이 관계를
만족한다. route_cache_max_age는 message_follow_duration
보다 5초 이상 작아야 하고, 각각 0이면 경로 캐시와 message 전달을 끈다. 위치 결정과 이전
동작은 Location과 Relocation이 다룬다.
8. STREAM node 옵션¶
| 옵션 | 무엇을 정하나 | 기본값 |
|---|---|---|
bind |
client가 접속할 주소 | 지정해야 한다 |
bind_host · advertise_host |
bind · 광고 주소 | 루트 값 |
| session 등록 | 연결마다 만들 session 타입 | 지정해야 한다 |
max_message_size |
client가 보내는 message 하나의 byte 상한 | 64 KiB |
| TLS 설정 | 서버 인증서와 client 인증서 요구 여부 | 평문, client 인증서를 요구하지 않음 |
| Actor dispatch | 들어온 packet을 bind된 Actor로 전달 | 꺼져 있음 |
max_message_size는 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에 배치되는 비중 |
class channel_weight_handler_t
{
public:
explicit channel_weight_handler_t (fw::route_mesh_runtime_options_t &mesh) : _mesh (mesh) {}
fw::http_response_t handle (const fw::http_request_t &request)
{
const auto channel = request.route_values.at ("channel");
const auto given = request.query_values.find ("value");
if (given == request.query_values.end ())
return fw::http_response_t{400, R"({"error":"value is required"})"};
const auto value = std::stoi (given->second);
auto &options = _mesh.channel (channel);
options.weight (value);
return fw::http_response_t{
200, nlohmann::json{{"channel", channel}, {"weight", options.weight ()}}.dump ()};
}
private:
fw::route_mesh_runtime_options_t &_mesh;
};
두 값의 범위는 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
- 언어별 표면 이름 — 주요 타입 사용 색인