{ "version": "1.1", "id": "a1-transport-vs-discovery", "title": "발견과 전송은 다른 경로다", "question": "TCP 7800 을 끊으면 무엇이 깨지고 무엇이 남는가", "type": "architecture", "direction": "TB", "audience": [ "Keycloak 클러스터의 장애 범위를 가늠하려는 엔지니어" ], "summary": "세션 공유는 데이터베이스를 지나므로 7800 과 무관하다. 로그아웃 무효화 통지는 7800 을 타므로 끊으면 전파되지 않는다.", "alt": "두 노드가 데이터베이스로는 이어져 있고 TCP 7800 으로는 끊긴 구성. 세션 조회는 살아 있고 무효화 통지는 막힌다.", "long_description": "노드가 서로를 찾는 경로와 실제로 이야기하는 경로가 다르다. 발견은 PostgreSQL 의 JGROUPS_PING 테이블을 쓰고 전송은 TCP 7800 을 쓴다. 7800 만 막으면 둘 다 데이터베이스에 등록된 채로 남아 서로 존재한다고 믿지만 메시지는 오가지 않는다. 세션은 데이터베이스에 있으므로 교차 노드 refresh 는 200 을 유지하고, 로그아웃 무효화 통지는 7800 을 타므로 400 이어야 할 것이 200 이 된다.", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", "anchor": { "kind": "heading", "value": "A-1 · JGroups 전송(TCP 7800) 차단", "line": 185 } }, "composition": { "profile": "component-flow", "diagram_only": true, "reference_ids": [ "payment-event-flow" ], "rationale": "무엇이 어느 경로를 타는가가 지배적 질문이다. 경로의 분기이므로 component-flow 를 골랐다." }, "groups": [], "nodes": [ { "id": "k0", "label": "keycloak-0", "kind": "service", "role": "source", "emphasis": "primary", "description": "로그아웃을 처리한 노드.", "details": [], "evidence": [ { "start_line": 183, "end_line": 189 } ], "assumption": false }, { "id": "transport", "label": "TCP 7800", "kind": "channel", "role": "control", "emphasis": "warning", "description": "무효화 통지가 지나는 길. NetworkPolicy 로 막았다.", "details": [ "허용 포트 8080 · 9000" ], "evidence": [ { "start_line": 191, "end_line": 196 } ], "assumption": false }, { "id": "k1", "label": "keycloak-1", "kind": "service", "role": "target", "emphasis": "primary", "description": "통지를 못 받아 세션이 죽은 것을 모른다.", "details": [ "refresh 200 (기대 400)" ], "evidence": [ { "start_line": 183, "end_line": 189 } ], "assumption": false }, { "id": "db", "label": "PostgreSQL", "kind": "datastore", "role": "store", "emphasis": "primary", "description": "세션이 여기 있어 7800 과 무관하다.", "details": [ "교차 노드 refresh 200" ], "evidence": [ { "start_line": 186, "end_line": 190 } ], "assumption": false } ], "edges": [ { "id": "k0-t", "from": "k0", "to": "transport", "label": "무효화 통지", "kind": "request", "evidence": [ { "start_line": 186, "end_line": 190 } ], "assumption": false }, { "id": "t-k1", "from": "transport", "to": "k1", "label": "차단", "kind": "blocked", "evidence": [ { "start_line": 186, "end_line": 190 } ], "assumption": false }, { "id": "k1-db", "from": "k1", "to": "db", "label": "세션 SELECT", "kind": "read", "evidence": [ { "start_line": 186, "end_line": 189 } ], "assumption": false } ], "legend": [], "metadata": { "rationale": "발견과 전송을 분리해 그렸다. A-1 의 예측이 하나만 맞은 이유가 이 분기에 있다." } }