C.W.K.
Stream
Lesson 03 of 04 · published

listener 는 identity 가 아니다

~14 min · firelink, responder-identity, port-owner, health-check

Level 0식은 재
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"8100 에서 뭔가 listen 해. 귀엽네. 근데 그게 Ember 야 — 아니면 Ember 의 port 를 입은 유령이야?"

초록불 속 함정

순진한 health check 는 이래. 선언된 port 에 연결하고, 뭔가 답하면 'running' 이라 불러. 합리적으로 느껴지고 조용히 틀렸어. TCP listener 는 어떤 프로세스가 그 port 에 bind 됐다는 것만 증명해 — 기대한 product 인 건 아니라. 지난주에 안 죽은 남은 서버일 수도. port 를 먼저 잡은 다른 앱일 수도. placeholder, proxy, 완전히 무관한 프로세스일 수도. 그 하나하나가, 진실로는 거기 없는 서비스에 순진한 체크가 자신 있는 초록불을 보이게 만들어.

identity 를 증명하는 두 체크

Firelink 는 속기를 거부해서, responder identity 를 두 체크로 검증해. 첫째, port-owner 체크: office launchd 멤버는, 선언된 localhost port 가 그 job 자신의 process tree 에 소유돼야 해 — 그냥 열린 게 아니라, launchd job 이 실제로 spawn 한 프로세스가 쥔. 둘째, health-identity 체크: 선언된 health path 가 있는 멤버는 그 path 를 기대한 identity substring 으로 답해야 해 — 응답이 사실상 '응, 나 Ember 야'라고 말해야 해. 둘 다 통과하면 진짜로 도는 거야. 하나라도 실패하면 Firelink 는 불일치 detail 과 함께 unknown 을 보고해 — 절대 running 이 아니라.

왜 'unknown' 이 정직한 평결인가

identity 체크 실패에 'stopped' 를 보고하지도 않는 걸 봐. 뭔가 답하고 있어 — 그냥 옳은 것임이 증명 안 될 뿐. 그건 '죽음'이 아냐; '이게 주장하는 그것임을 확인 못 함'이야. running 이라 부르면 거짓말이고; stopped 라 불러도 거짓말이야. unknown 에 구체적 불일치를 더한 게 유일하게 정직한 답이고 — 그게 딱 사람이 '저 port 에 실제로 뭐가 앉아 있지?' 조사하러 가야 하는 걸 보는 데 필요한 state 야.

응답은 identity 의 증거가 아냐 — responder 가 주장하는 그 자신인지 검증하고, 못 하면 'unknown' 으로 낮춰. '뭔가 답했다'와 '옳은 게 답했다'는 다른 사실이야. 단순 연결을 건강으로 취급하는 시스템은 언젠가 진짜 트래픽을 유령한테 라우팅하고 내내 건강하다 부를 거야.

Code

responder 를 검증해 — listener 를 믿지 마·python
def verify_service(member) -> ServiceState:
    if not tcp_listening(member.host, member.port):
        return ServiceState("stopped")            # nothing there at all

    # Something is listening. That is NOT enough. Prove it's the right thing.

    # Check 1: port-owner — is the port held by this launchd job's process tree?
    if member.launchd_owned:
        owner = port_owning_pid(member.port)
        if owner not in process_tree(member.launchd_label):
            return ServiceState("unknown", why="port owned by a foreign process")

    # Check 2: health-identity — does the health path say it's really this member?
    if member.health_check:
        body = http_get(member.health_check.path)
        if member.health_check.identity_substring not in body:
            return ServiceState("unknown", why="health response identity mismatch")

    return ServiceState("running")                 # earned it: bound AND proven

# A leftover process on :8100 fails check 1 or 2 -> reported 'unknown',
# never a green 'running'. The port being open is not the answer.

External links

Exercise

네가 의존하는 아무 health check 를 잡고 물어봐. 여기서 'up' 이 정확히 뭘 뜻해? 'port 가 연결을 받음'이야, 'HTTP 200 이 돌아옴'이야, 아니면 '응답이 옳은 서비스와 버전임을 증명함'이야? 약한 체크는 건강하다 보고하는데 진짜 서비스는 없는 구체적 시나리오를 구성해봐 (남은 프로세스, proxy, 200 반환하는 점검 페이지). 그다음 그걸 잡을 identity 체크를 설명해.
Hint
강도의 사다리: port-open < connection-accepted < HTTP 200 < 응답에 identity/version 마커 포함. '모니터링이 놓친' outage 대부분은 'port 가 열려 있었다'보다 강한 걸론 안 잡혔어. identity 를 증명할 때까지 사다리 위로 밀어, 단순 존재 말고.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.