fix: 하네스 제거 및 keycloak 문서 보강
This commit is contained in:
@@ -1 +0,0 @@
|
||||
../../vault/10-projects/errors/jdk-httpclient-dns-unresolvedaddress-connectexception-2026-06-11.md
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: error / jdk-httpclient-dns-unresolvedaddress-connectexception-2026-06-11
|
||||
source_type: error-note
|
||||
status: raw
|
||||
related_branches: [feature-outbound-http-client-baseline]
|
||||
related_projects: [ca-skeleton]
|
||||
tags: [error, ca-skeleton, jdk-httpclient, dns, error-classification, outbound-http]
|
||||
created: 2026-06-11
|
||||
status_label: resolved
|
||||
---
|
||||
|
||||
# error: jdk-httpclient-dns-unresolvedaddress-connectexception-2026-06-11
|
||||
|
||||
> Layer: `raw/errors/` — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.
|
||||
|
||||
## Parent / 부모
|
||||
|
||||
- [[raw/branch-notes/feature-outbound-http-client-baseline]] — D12 실패 분류(error mapper) 통합 테스트 작성 중 발견.
|
||||
|
||||
## 증상 / Symptom
|
||||
|
||||
- 에러 메시지 (구현 에이전트 보고 원문 발췌 — 테스트 red 단계):
|
||||
```text
|
||||
red: ./gradlew :adapter-outbound:test --tests '*.OutboundHttpClientTest' --console=plain
|
||||
→ 4 FAILED (... t4 CONNECT_FAILED not DNS_FAILED ...)
|
||||
```
|
||||
- 발생 컨텍스트: `OutboundHttpClient.get("http://nonexistent-host-zzz.invalid", ...)` 호출 시 `OutboundHttpErrorMapper` 가 `DEPENDENCY_DNS_FAILED` 가 아니라 `DEPENDENCY_CONNECT_FAILED` 를 반환.
|
||||
- 발생 환경: local, JDK 21 (`JdkClientHttpRequestFactory` + `java.net.http.HttpClient`).
|
||||
- 재현 가능 여부: `always`.
|
||||
|
||||
## 재현 절차 / Reproduction
|
||||
|
||||
1. JDK 21 `HttpClient` 기반 Spring `RestClient` 로 존재하지 않는 호스트(`*.invalid`)에 GET 요청.
|
||||
2. cause chain 을 단일 패스로 위에서부터 매칭하는 분류기(`UnknownHostException|UnresolvedAddressException` 규칙이 `ConnectException` 규칙보다 우선순위가 높아도, 체인 순서상 `ConnectException` 이 먼저 등장)를 통과.
|
||||
3. 기대: `DEPENDENCY_DNS_FAILED`.
|
||||
4. 실제: `DEPENDENCY_CONNECT_FAILED` — JDK 21 `HttpClient` 가 DNS 실패를 `ConnectException(cause=ConnectException(cause=UnresolvedAddressException))` 으로 래핑하기 때문에, 체인을 바깥에서부터 한 번만 훑는 분류기는 바깥쪽 `ConnectException` 에서 먼저 멈춘다.
|
||||
|
||||
## 조사 단계 / Investigation log
|
||||
|
||||
- 2026-06-11 — t4 red 관측 → 예외 cause chain 출력으로 `ConnectException → ConnectException → UnresolvedAddressException` 중첩 구조 확인 (JDK 21 로컬 검증).
|
||||
- 2026-06-11 — 분류 규칙 순서 조정만으로는 해결 불가(체인 등장 순서 문제) → `ConnectException` 매칭 시 잔여 서브 체인을 `hasDnsCauseInChain()` 으로 추가 스캔, DNS 근원 발견 시 `DEPENDENCY_DNS_FAILED` 우선 반환하도록 수정 → t4 green, 기존 mapper 단위테스트 19/19 회귀 없음.
|
||||
|
||||
## 근본 원인 / Root cause
|
||||
|
||||
- 직접 원인: 분류기가 cause chain 에서 **먼저 등장하는** 예외 타입으로 결정 — 바깥 래퍼(`ConnectException`)가 안쪽 근원(`UnresolvedAddressException`)을 가림.
|
||||
- 근본 원인: JDK `HttpClient` 의 예외 래핑 구조(DNS 실패도 `ConnectException` 으로 노출)가 "타입 우선순위 = 체인 등장 순서" 가정과 충돌.
|
||||
- 트리거 조건: JDK 21 `HttpClient` + 미해석 호스트명. (`needs-confirmation`: 다른 JDK 버전/다른 `ClientHttpRequestFactory` 의 래핑 구조는 미검증.)
|
||||
|
||||
## Sources / 근거
|
||||
|
||||
- 로컬 검증: `OutboundHttpClientTest.t4_unknown_host_*` (JDK 21) — 수정 전 red / 수정 후 green. 외부 공식 문서 인용 없음 (JDK 예외 래핑 구조는 로컬 관측 기반).
|
||||
|
||||
## 해결 / Resolution
|
||||
|
||||
- 적용한 조치: `OutboundHttpErrorMapper` — `ConnectException` 매칭 시 `hasDnsCauseInChain()` helper 로 서브 체인에서 `UnknownHostException`/`UnresolvedAddressException` 을 추가 탐색, 발견 시 DNS 분류 우선.
|
||||
- 검증 방법: `./gradlew :adapter-outbound:test` — `OutboundHttpClientTest.t4` + `OutboundHttpErrorMapperTest` 19/19 PASS.
|
||||
- 잔여 위험: factory 교체(Apache/Jetty 등) 시 래핑 구조가 달라질 수 있음 — 계약 테스트가 회귀를 잡음.
|
||||
|
||||
## 회고 / Lessons
|
||||
|
||||
- 빨리 감지하는 신호: "DNS 실패가 CONNECT_FAILED 로 잡힘" / 분류 테스트에서 인접 카테고리 오분류 → 예외 cause chain 전체를 덤프해 래핑 구조부터 확인.
|
||||
- 예방 체크리스트: 예외 분류기는 "타입 우선순위" 와 "체인 등장 순서" 를 분리해 설계 — 특정 근원(DNS)이 래퍼(connect)보다 우선해야 하면 서브 체인 스캔을 명시.
|
||||
- wiki 일반화 후보: "cause-chain 기반 예외 분류기의 우선순위 함정" (wiki/concepts 추출 후보).
|
||||
|
||||
## Related / 관련
|
||||
|
||||
- 같은 red 라운드에서 발견된 인접 오분류: connect-refused 가 `HttpConnectTimeoutException extends HttpTimeoutException` 상속 때문에 TIMEOUT 으로 새는 문제 — 분류 규칙 순서(connect-timeout 을 read-timeout 보다 먼저)로 해결 (branch note §Cluster Errors 기록).
|
||||
Reference in New Issue
Block a user