Documentation
¶
Overview ¶
Package server 把 relay、channel 与 plugin 装配成一个可监听的 HTTP 服务, 对外暴露四种方言的端点。
装配规则只有一条:client 方言与渠道方言相同时按字节透传,不同时经 relay 转换。 插件在四个时机介入,插件失败不影响转发可用性。
Index ¶
Constants ¶
const SessionHeaderName = "X-TokenMP-Session"
SessionHeaderName 是客户端声明会话标识的请求头。
同一段会话的连续请求带上同一个值,core 会把它们粘到同一个上游渠道上,让上游 的提示缓存有机会命中。这个头只在本进程内使用,不会转发给上游。
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Attempt ¶ added in v0.3.0
type Attempt struct {
Channel string
Dialect dialect.Name
Upstream string
// Status 是上游返回的状态码。0 表示没拿到上游响应,原因看 Failure。
Status int
// Failure 是没拿到上游响应的原因,Status 非 0 时恒为 FailureNone。
Failure Failure
// Duration 是这次尝试的耗时,从选定候选算到拿到响应头或失败。
Duration time.Duration
}
Attempt 是一次候选尝试。
type Failure ¶ added in v0.3.0
type Failure string
Failure 是一次尝试没拿到上游响应的原因。
取值封闭:不把上游的错误文字带进来。那是客户端与上游可控的字符串,长度没有上限, 放进公开面就得跟着定一套截断口径。原因文字在 WARN 日志里。
type Option ¶ added in v0.3.0
type Option func(*Options)
Option 覆盖 FromConfig 的装配参数。
func WithMiddleware ¶ added in v0.4.0
WithMiddleware 设置包住内核处理器的宿主中间件,见 Options.Middleware。
func WithRequestDone ¶ added in v0.3.0
WithRequestDone 设置每次请求结束时调用的回调,见 Options.OnRequestDone。
func WithoutAccessLog ¶ added in v0.4.0
func WithoutAccessLog() Option
WithoutAccessLog 关掉内核自己那两行访问日志,见 Options.DisableAccessLog。
type Options ¶
type Options struct {
// Config 是配置,必填。
Config *config.Config
// Channels 是渠道客户端集合,必填。
Channels *channel.Set
// Plugins 是插件集合,为 nil 时视为没有插件。
Plugins *plugin.Store
// Engine 是转换内核,为 nil 时按配置构造。
Engine *relay.Engine
// Logger 是日志入口,为 nil 时丢弃日志。
Logger *slog.Logger
// Now 返回当前时间,为 nil 时用 time.Now。
Now func() time.Time
// MaxBodyBytes 是单个请求体的上限,为 0 时用 config.DefaultMaxBodyBytes。
MaxBodyBytes int64
// OnRequestDone 在每次请求结束时同步调用,交出这次请求的原始量。
//
// ctx 是本次请求一直沿用下来的那个:宿主在 Options.Middleware 里加进 context 的
// 值在这里能读到,用来把请求级的记账状态跟结束时这份原始量对上。
//
// 为 nil 时什么也不做,也不构造 Outcome。
OnRequestDone func(context.Context, Outcome)
// Middleware 包住内核的整个处理器,包括访问日志。宿主在这里记自己的日志、
// 测首字节、加响应头、接 tracing,也可以换掉请求体(内核从 request.Body 读,
// 换过之后参与路由的就是新内容)或根本不调用 next。
//
// 装在外侧:宿主加进 context 的值会一路传下去,OnRequestDone 的 ctx 里有它。
//
// 改请求头不会传到上游:上游请求头来自渠道配置与 `Auth`,内核不从进来的请求里抄。
//
// 包装 http.ResponseWriter 时必须把 Flush 转发下去,否则流式响应会静默退化成
// 不刷新。
//
// 为 nil 时什么都不装。
Middleware func(http.Handler) http.Handler
// DisableAccessLog 关掉内核自己那两行访问日志。
//
// 关掉的是「请求进入」与「请求完成」,包括失败请求的 WARN 完成行;request_id 仍然
// 生成、其余 WARN 行照旧带着它,OnRequestDone 也不受影响。
// 进入行里的 client 与 user_agent 会一起没有,需要的话从 Outcome 的同名字段自己记。
// 默认为 false,即照常记录。
DisableAccessLog bool
}
Options 是服务的装配参数。
type Outcome ¶ added in v0.3.0
type Outcome struct {
// RequestID 是这次请求的 id,与访问日志里的 request_id 相同。
RequestID string
Method string
Path string
// Client 是去掉端口之后的客户端地址,UserAgent 是请求头里的 User-Agent。
Client string
UserAgent string
// Status 是写回客户端的状态码。处理器没有显式写响应头时按 200 记,与访问日志一致。
Status int
// Duration 是从请求进入中间件到处理器返回的时长,含重试与等待上游的全部时间。
Duration time.Duration
// FirstByte 是从请求进入中间件到首次写出响应体的时长,也就是 core 能测到的 TTFT。
// 整个请求没有写出过响应体时为 0。
//
// 只算响应体,不算响应头:流式路径拿到上游响应头就写响应头,而第一个分片可能过很久
// 才到,按响应头记会让 TTFT 系统性偏小。非流式响应是一次写完的,这个值因此约等于
// Duration,看不出 TTFT——该不该算由宿主按 Streaming 自己判断。
FirstByte time.Duration
// BytesWritten 是写回客户端的响应体字节数,不含响应头。
BytesWritten int64
// Model 是插件改写之后参与匹配的模型名。Channel 是实际服务的那条渠道,降级换过
// 渠道时是真正服务的那个;没有一条候选服务成功时为空串。
Model string
Channel string
// Streaming 报告客户端是否要求流式,取自请求内容,不是上游实际按流式回的。
Streaming bool
// Attempts 按顺序记下每条候选尝试的耗时与状态,长度与访问日志的 attempts 相同。
Attempts []Attempt
// Usage 是上游给出的用量,上游没给时为 nil。
Usage *Usage
}
Outcome 是一次请求结束时交给宿主的原始量。
只交原始量,不算指标。指标口径随宿主变:TTFT 是从请求进入算还是从上游首字节算, TPS 的分母取总时长还是生成时长,core 算出来的一定不合宿主的意。宿主拿这些量自己算。
字段是每次请求都会填的,没有「有时有有时没有」的项:上游没给用量时 Usage 为 nil, 这是唯一的可选项。
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server 是一个转发服务。
func FromConfigWith ¶ added in v0.3.0
FromConfigWith 与 FromConfig 相同,另外可以用 opts 覆盖装配参数。
做成单独一个函数而不是给 FromConfig 加可变参数:可变参数会让它不再能赋给 func(*config.Config, *slog.Logger) (*Server, error) 类型的变量,按仓库的兼容 承诺算破坏性变更。要完全掌控装配就直接用 New。