Skip to content

feat(connectivity): dynamic CheckOpts — skip unconfigured probes, clamp check_interval (#1011) - #4

Open
itoywh wants to merge 14 commits into
kdaefrom
pr/1011-dynamic-checkopts
Open

itoywh wants to merge 14 commits into
kdaefrom
pr/1011-dynamic-checkopts

Conversation

@itoywh

@itoywh itoywh commented Jul 20, 2026

Copy link
Copy Markdown
Owner

来源

从 daeuniverse/dae 官方 PR #1011 迁移至自维护库 itoywh/kdae。

  • 原 PR base=daeuniverse/dae:main,head=itoywh/dae:feat/dynamic-checkopts
  • 本 PR 将 13 个 commit cherry-pick 到 kdae 基线(olicesx kdae 线 5277310),零冲突

功能

  • dynamic CheckOpts:未配置的探针自动跳过
    • 未配 IPv6 检查 → 不发 IPv6 探测(tcp6/udp6 按协议独立判断)
    • 未配 udp_check_dns → DNS-UDP 收集重定向到 TCP
  • check_interval 下限钳制 2s(防探测风暴,超下限 WARN 日志)
  • 健康检查禁用时消息从 Debug 提升到 Warn
  • 探针卡死 guard + 诊断日志

改动文件

  • component/outbound/dialer/connectivity_check.go (+108) — 核心
  • component/outbound/dialer/dialer.go (+8)
  • control/control_plane.go (+6)
  • install/dae.service (+2/-1) — 去掉 --disable-timestamp
  • README.md (+47) — connectivity check 配置参考

备注

  • 原 PR 含 CHANGELOGS.md 改动(daeuniverse main 线 release notes),已 drop(auto-generated,不适用于 kdae 线)
  • ⚠️ 合并注意:本 PR 与 PR feat(outbound): fixed_fallback support (#1009) #1 (#1009 fixed_fallback) 都改 connectivity_check.go。两功能区域不同,合并大概率可自动进行;若冲突需手动解决(保留两侧逻辑)

LiYang and others added 14 commits July 20, 2026 18:08
- Add shouldSkipIpv6Probes(): detects if config has only explicit IPv4 addresses
- Add hasUdpDnsConfig(): checks if udp_check_dns is configured
- Build CheckOpts slice dynamically in aliveBackground() instead of hardcoded 4 probes
- Debug log shows which probes are active on dialer start
- Skip NotifyPeriodicCheckResultForType for UDP when not configured

This avoids unnecessary IPv6 connectivity probes when the user's network
has no IPv6 support, and skips UDP DNS probes when udp_check_dns is unset.
- Replace shouldSkipIpv6Probes() with shouldSkipTcp6Probes() and
  shouldSkipUdp6Probes() — each checks only its own config
- tcp_check_url having IPv6 no longer forces udp6CheckDnsOpt
- udp_check_dns defaults no longer affect tcp6 decision
- IPv6 probes are skipped per-protocol when only explicit IPv4
  addresses are configured in the respective check option
…ning

- Add node DEAD/ALIVE state change logging
- Add detailed traffic path recovery logging
- Improve health check disabled warning message
- Add markAvailableTraffic for node recovery detection
- connectivity_check.go: Debugln → Warnln for check_interval=0 and
  no checks configured (production-critical, users must see this)
- control_plane.go: add global WARN at startup if all three health check
  config fields (check_interval, tcp_check_url, udp_check_dns) are unset
…is configured

When udp_check_dns is not configured, DNS-UDP collections (IdxDnsUdp4/6)
are never probed by the health check background loop. Their Alive flag
stays true forever (initial value from newCollection()).

This false-positive 'alive' breaks the fixed_fallback retry state machine:
- DNS resolution calls Select(udp4) first → MustGetAlive=true → resets
  fixedFallbackDeadSince=0 and fixedFallbackRetryCount=0
- The next Select(tcp4) has to start the timeout from scratch
- This repeats every DNS resolution cycle, so retryCount never advances
  and fallback never triggers.

Fix: redirect DNS-UDP collection lookups to the same IP version's TCP
collection when no udp_check_dns is configured. DNS-UDP and TCP share
the same (correct) Alive value, eliminating the spurious reset.
- Add health check parameters table
- Add dynamic probe selection explanation
- Add configuration examples (minimal, TCP-only, full)
- Mention 2s clamp with WARN log
- Add timeout guard in aliveBackground: if probes take longer than
  cycle+5s, log WARN and continue cycling instead of blocking forever
- Add debug log when probe is skipped due to empty AliveDialerSet
  (helps diagnose silent probe gaps)
…ead of read-path redirect

The previous attempt (commit 2ef37d72) redirected DNS-UDP collection lookups to
the same IP version's TCP collection inside mustGetCollection to fix a
fixed_fallback retry-state-machine bug. However, it only redirected the READ
path: ReportUnavailableForced / markUnavailableInternal keep writing to the
distinct DNS-UDP collection (typ.Index()), so a forced DNS-UDP unavailable was
never reflected by MustGetAlive, breaking UDP health-domain independence tests.

This change implements the intended 'share the same Alive value' behavior the
right way: when udp_check_dns is not configured, alias the DNS-UDP collection
pointer to the TCP collection at dialer construction (mirroring the existing
IdxDnsTcp4 -> IdxTcp4 aliasing). Read and write now hit the same struct, so
domain independence is preserved (Data-UDP stays a separate collection) while
DNS-UDP correctly reflects TCP's probed state.

Also removes an unrelated AppendLatency(Timeout) call that was wrongly added to
markUnavailableInternal; health-check failures must not append latency samples
(matches upstream test contract).
The pointer-alias that coupled the DNS-UDP collection to the TCP collection
broke UDP health-domain independence and snapshot/restore semantics
(TestRestoreHealthSnapshotRestoresCollectionState,
TestChooseProxyDialer_AdmitsDataUdpViaTcpFallback, and the UDP health domain
independence tests).

Restore independent DNS-UDP collections. This branch carries no fixed_fallback
retry state machine, so the alias served no purpose here other than coupling
the collections; the fixed_fallback retry liveness handling lives on the
pr1-fixed-fallback branch via Dialer.AliveForRetry.
This logging is now owned by the fixed_fallback PR (#1009), which
revolve around node alive/dead lifecycle. Keeping it here would
duplicate the logs across two PRs. #1011 retains its core scope:
dynamic CheckOpts, skip logic, check_interval clamp, opt-in
warnings, and latency tracking.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant