targetclient

package
v0.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

本文件实现 agentd 常驻侧的 target 客户端复用池。

职责:

  • 按 target 名缓存客户端与其 relay 隧道,一台机器一条隧道、全子系统共用
  • 配置变更时失效重建,target 删除时关掉并移出
  • Names 提供「当前有哪些机器」的唯一判据(活快照)

边界:

  • 不探活:拿到 client 之后怎么用、算不算可达,由调用方决定
  • 不预热:预热在 warm.go,两者刻意分开(隧道通没通 ≠ 对端活没活)
  • 调用方**不**负责关闭 For 返回的 client:隧道归池,进程退出时统一 Close

本包收拢「按 target 形态选路构造 agentd 客户端」这唯一判据。

职责:

  • New:一次性工厂,按 Target 是 relay 还是直连造出对应 client(CLI 用)
  • Pool(见 pool.go):常驻复用池,一台机器一条 relay 隧道(agentd 用)

边界:

  • 不做任何网络请求:New 只构造,隧道由 Dialer 惰性建立或由 Warm 预热
  • 不碰 client 的上层语义:MarkForwarded / NoRedirect 等一律由调用方链式调用
  • 不读配置文件:调用方给什么 Target 就按什么造

为什么要有这个包:选路判据曾经存在两份——CLI 有 relay 分支,agentd 侧六处扇出 一处都没有,于是 relay 机器在控制台一律显示「已断开」。判据只留一份,才不会 有第二份从来没被写出来。

本文件实现 relay 隧道的后台预热。

职责:周期性地对每台 relay 机器主动建隧道,让探活拿到的是一条已经就绪的通道

边界:

  • **预热只保证隧道,不代表可达**:隧道通了但对端 agentd 没起,机器照样是 「已断开」。两个判据不合并——合并会让「网络不通」和「服务没起」这两种 完全不同的故障显示成同一句话
  • 不碰直连机器:它们没有隧道可预热
  • 不占探活预算:探活只有 3s,而首次建隧道要 WSS 拨号 + CONNECT + E2E 握手

Index

Constants

This section is empty.

Variables

View Source
var ErrNoEndpoint = errors.New("target 既没有 addr 也没有 relay")

ErrNoEndpoint 表示这个 target 既没有 addr 也没有 relay,无从构造客户端。

config.Target.Validate 早就写着「direct target addr 不能为空」,这里是同一条 不变式在扇出侧的落点——扇出侧过去从没问过它。

Functions

func New

func New(name string, t config.Target, log *slog.Logger) (*client.Client, func(), error)

New 按 Target 形态选路,构造一个一次性的 agentd 客户端。

参数:

  • name: target 名,只用于日志与错误文案(会原样显示给用户)
  • t: target 配置;t.IsRelay() 为真走 relay 隧道,否则直连 t.Addr
  • log: 日志器;nil 时用 slog.Default()

返回:

  • client: 可直接链式 MarkForwarded()/NoRedirect()
  • cleanup: **恒非 nil**,调用方 defer 它即可(直连形态是 no-op)
  • err: ErrNoEndpoint(无端点)或 relay token 熵不足

注意:

  • 不发任何网络请求;relay 隧道由 Dialer 首次用到时惰性建立
  • 常驻场景不要用它——每次调用都会新建一条 relay 隧道,用 Pool

Types

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool 是按 target 名缓存的客户端池。

并发安全:全部字段访问都在 mu 保护下;conf 由调用方保证并发安全 (agentd 侧传的是 Server.conf,读的是 atomic 快照)。

func NewPool

func NewPool(conf func() *config.Config, log *slog.Logger) *Pool

NewPool 构造复用池。

参数:

  • conf: 取当前配置快照的函数;**每次 For/Names 都会现调**,池因此跟随活配置
  • log: 日志器;nil 时用 slog.Default()

func (*Pool) Close

func (p *Pool) Close() error

Close 关掉池内全部客户端与隧道,之后 For 一律报错。

注意:relay.Dialer.Close 是终态(closed 标志阻止重连),所以池关了就不会 再复活——这符合进程退出语义,不要在运行期调它来「清一下缓存」。

func (*Pool) For

func (p *Pool) For(name string) (*client.Client, error)

For 取一台机器的客户端,必要时构造或重建。

参数:

  • name: target 名,必须已在配置里登记

返回:

  • client: **调用方不负责关闭**——隧道归池所有,进程退出时由 Close 统一关
  • err: 机器未登记、池已关闭、或 New 的选路错误(ErrNoEndpoint / token 熵不足)

注意:不发任何网络请求。relay 隧道由 Dialer 惰性建立或由 Warm 预热。

func (*Pool) Names

func (p *Pool) Names() []string

Names 返回当前配置里全部 target 名,已排序。

排序是为了让 UI 列表与日志顺序稳定:每次刷新都跳序会让人以为数据在变。

func (*Pool) Warm

func (p *Pool) Warm(ctx context.Context)

Warm 跑预热循环,阻塞直到 ctx 取消。

参数:

  • ctx: 生命周期;取消即返回

注意:

  • 只对 relay 形态的 target 生效
  • 单台失败按 1s→60s 指数退避,退避期内跳过该台,不影响其余
  • 新增的机器由下一轮扫到;删除的机器自然不再出现在 Names() 里

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL