
如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
弃用通知: 该包将于2024年1月30日归档为只读状态。此后,该仓库将不再在Github上维护。
本项目将所有高效工具聚合到一个HTTP反向代理中,移除应用代码中对工具的直接引用,并扩展了可使用这些工具的语言/技术栈范围。提供的功能包括:
本项目是HTTP客户端中间件项目(https://github.com/asecurityteam/transport%E3%80%81https://github.com/asecurityteam/httpstats%E5%92%8Chttps://github.com/asecurityteam/loadshed%EF%BC%89%E7%9A%84%E9%85%8D%E5%A5%97%E5%B7%A5%E5%85%B7%EF%BC%8C%E5%B0%86%E8%BF%99%E4%BA%9B%E5%BA%93%E5%8C%85%E8%A3%85%E5%9C%A8%E7%8B%AC%E7%AB%8B%E8%BF%90%E8%A1%8C%E6%97%B6%E4%B8%AD%EF%BC%8C%E5%8F%AF%E5%9C%A8%E4%B8%BB%E5%BA%94%E7%94%A8%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96%E7%BB%B4%E6%8A%A4%E3%80%82
我们继续将这些核心工具作为库维护,用于Go中更高性能、更具弹性和更好可操作性的HTTP客户端调用。然而,多年来我们开始突破通用库的能力边界,并开始构建通用运行时层以提高易用性。主要面临两个问题:1)Go系统需要大量复制粘贴代码来导入、配置和安装工具,导致项目间出现细微差异;2)无法在Go以外的系统中共享库的改进。
注意,本项目旨在满足将现有库适配更多服务的简单需求。我们不打算将其发展为全功能的"智能代理"或"服务网格"设备。虽然功能上有一定重叠,但我们不会专注于服务发现或多协议支持。对于此类功能,建议使用https://github.com/Netflix/zuul%E9%85%8D%E5%90%88https://github.com/Netflix/eureka%E6%88%96Lyft%E7%9A%84Envoy%E3%80%82
该代理基于OpenAPI构建,使用OpenAPI规范作为配置。它在文档的特定关键点查找一组扩展。以下是系统运行所需的配置位置和扩展说明。
HTTP服务器由我们的另一个库https://github.com/asecurityteam/runhttp%E6%8F%90%E4%BE%9B%EF%BC%8C%E5%B9%B6%E5%9C%A8OpenAPI%E8%A7%84%E8%8C%83%E4%B8%AD%E5%8C%85%E5%90%AB%E8%87%AA%E5%B7%B1%E7%9A%84%E6%89%A9%E5%B1%95%E9%83%A8%E5%88%86%E3%80%82%E7%B3%BB%E7%BB%9F%E5%B0%86%E6%9F%A5%E6%89%BE%E5%90%8D%E4%B8%BA%60x-runtime%60%E7%9A%84%E9%A1%B6%E7%BA%A7%E6%89%A9%E5%B1%95%EF%BC%8C%E5%B9%B6%E4%BD%BF%E7%94%A8%E5%85%B6%E5%86%85%E5%AE%B9%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%9A
yamlx-runtime: signals: # ([]string) 安装的信号处理器。可选值:OS installed: - "OS" os: # ([]int) 监听的信号 signals: - 15 - 2 stats: # (string) 指标输出目标流。可选值:NULLSTAT, DATADOG output: "DATADOG" datadog: # (int) 发送的最大数据包大小 packetsize: 32768 # ([]string) 所有指标的静态标签 tags: # (time.Duration) 向监听器发送指标的频率 flushinterval: "10s" # (string) 发送指标时使用的监听器地址 address: "localhost:8125" logger: # (string) 日志输出目标流。可选值:STDOUT, NULL output: "STDOUT" # (string) 日志输出的最低级别。可选值:DEBUG, INFO, WARN, ERROR level: "INFO" httpserver: # (string) 服务器监听地址 address: ":8080"
除运行时外,系统还要求所有后端配置位于名为x-transportd的顶级扩展中。后端配置用于将反向代理链接到一个或多个其他系统。每个后端配置包含目标主机名和连接池设置:
yamlx-transportd: # ([]string) 可用后端列表。名称为符号化名称,供后续引用 backends: - "backendName" backendName: # (string) 后端主机URL host: "https://localhost" pool: # (int) 连接池数量。仅在使用HTTP/2时使用>1 count: 1 # (time.Duration) 连接池刷新前的生命周期 ttl: "1h0m0s"
如果代理需要允许未识别的路由通过到后端,则必须指定名称为default的后端。此后端必须包含一个名为allowUnknown的额外键,其中包含路由设置的等效配置(下一节将详细说明)。例如:
yamlx-transportd: # ([]string) 可用后端列表。名称为符号化名称,供后续引用 backends: - "default" default: # (string) 后端主机URL host: "https://localhost" pool: # (int) 连接池数量。仅在使用HTTP/2时使用>1 count: 1 # (time.Duration) 连接池刷新前的生命周期 ttl: "1h0m0s" allowUnknown: enabled: - "accesslog"
此中间件配置将应用于所有未知路由,然后再将其代理到默认后端。
OpenAPI规范中的每个路由都需要自己的x-transportd扩展块,以配置所需的特定客户端行为。每个块必须包含相关的后端引用、已安装中间件的有序列表以及任何已安装中间件的特定设置:
yamlx-transportd: # ([]string) 为此路由启用的组件有序列表 enabled: - "metrics" - "accesslog" - "asapvalidate" - "validateheaders" - "timeout" - "hedging" - "retry" - "retryafter" # 当存在并可解析429响应码和Retry-After响应头时,遵循该设置 - "asaptoken" - "requestvalidation" - "responsevalidation" - "strip" - "requestheaderinject" - "responseheaderinject" - "basicauth" # (string) 此路由的后端目标 backend: "backendName" metrics: # (string) 包含路径引用的标签名称 pathtag: "client_path" # (string) 包含后端引用的标签名称 backendtag: "client_dependency" # (string) 空闲连接返回计数指标名称 putidle: "http.client.put_idle" # (string) 发送和接收字节总数指标名称 bytestotal: "http.client.bytes_total" # (string) 发送字节数指标名称 bytessent: "http.client.bytes_sent" # (string) 接收字节数指标名称 bytesreceived: "http.client.bytes_received" # (string) 首字节响应时间指标名称 firstresponsebyte: "http.client.first_response_byte.timing" # (string) 写入头时间指标名称 wroteheaders: "http.client.wrote_headers.timing" # (string) TLS时间指标名称 tls: "http.client.tls.timing" # (string) 空闲时间指标名称 connectionidle: "http.client.connection_idle.timing" # (string) TCP时间指标名称 tcp: "http.client.tcp.timing" # (string) DNS时间指标名称 dns: "http.client.dns.timing" # (string) 总时间指标名称 timing: "http.client.timing" accesslog: # (string) 用于检查请求主体的头名称(多个头以逗号分隔,按顺序作为备选) principalheader: "X-Principal" asapvalidate: # ([]string) 公钥下载URL keyurls: # (string) 可接受的受众字符串 allowedaudience: "" # ([]string) 可接受的发行者字符串 allowedissuers: validateheaders: # (map[string][]string) 允许检查值的头列表 allowed: accept: - "text/json" - "text/html" # (map[string] string) 单行头值的分隔符 split: accept: "," timeout: # (time.Duration) 请求取消前的持续时间 after: "175ms" hedging: # (time.Duration) 打开新请求前的持续时间 interval: "50ms" retry: # (time.Duration) 请求之间的等待时间 backoff: "50ms" # (int) 最大重试次数 limit: 3 # ([]int) 触发重试的HTTP状态码 codes: - 500 - 501 - 502 - 503 - 504 - 505 - 506 - 507 - 508 - 509 - 510 - 511 # (bool) 请求之间的等待时间是否加倍 exponential: "false" asaptoken: # ([]string) 包含在令牌中的JWT受众值 audiences: # (string) 包含在令牌中的JWT发行者值 issuer: "" # (time.Duration) 令牌的生命周期 ttl: "0s" # (string) 包含在令牌中的JWT kid值 kid: "" # (string) 用于签名令牌的RSA私钥 privatekey: "" strip: # (int) 重定向前从路径开头移除的URL段数量 count: 0 requestheaderinject: # (map[string][]string) 要注入的头名称:值映射 headers: x-header-1: - "value1" x-header-2: - "value2" responseheaderinject: # (map[string][]string) 要注入的头名称:值映射 headers: x-header-1: - "value1" x-header-2: - "value2" basicauth: # (string) HTTP基本认证使用的用户名 username: "" # (string) HTTP基本认证使用的密码 password: ""
对于静态YAML文件不足的情况(如部署到需要略有不同配置的多个环境或区域),我们还支持在OpenAPI规范中使用环境变量引用。在验证文档和加载配置之前,系统将查找${}模式,并将所有实例替换为模式中标识的环境变量值。例如,${FOO}将获取FOO环境变量并插入其值。
遗憾的是,Go对动态加载插件的支持不佳,标准库plugin包的替代方案都需要某种形式的多处理和RPC。因此,添加核心集之外的功能需要创建此项目的自定义构建。
有关处理头验证等功能的自定义组件文档,请参见docs/components.md。
本项目使用我们的另一个库https://github.com/asecurityteam/settings%E6%9D%A5%E7%AE%A1%E7%90%86%E9%85%8D%E7%BD%AE%E5%92%8C%E6%8F%92%E4%BB%B6%E3%80%82%E7%BB%84%E4%BB%B6%E7%9A%84%E5%AE%8C%E6%95%B4%E5%8A%9F%E8%83%BD%E9%9B%86%E5%8F%AF%E5%9C%A8%60settings%60%E6%96%87%E6%A1%A3%E4%B8%AD%E6%89%BE%E5%88%B0%E3%80%82%E4%B8%BA%E6%96%B9%E4%BE%BF%E8%B5%B7%E8%A7%81%EF%BC%8C%E4%BB%A5%E4%B8%8B%E6%98%AF%E6%91%98%E8%A6%81%EF%BC%9A
插件不需要直接引用此项目,也不需要直接引用settings项目。所有新组件必须具有三个基本功能:1)定义配置结构体,2)实现settings.Component接口,3)路由感知的组件构造函数。最好通过现有插件来演示这一点。以下是timeout插件的带注释源代码:
golangpackage myplugin import ( "context" "net/http" "time" ) const ( defaultTimeoutSettingAfter = 175 * time.Millisecond ) // 所有核心功能应构建为http.RoundTripper接口的装饰器。目标是在不需要组件间紧密耦合的情况下分层添加功能。 // 装饰器的一般模式是一个结构体,它接受包装的http.RoundTripper并公开自己的RoundTrip方法。 type timeoutRoundTripper struct { Wrapped http.RoundTripper after time.Duration } // RoundTrip是满足http.RoundTripper接口所需的方法,允许装饰器表现为底层HTTP客户端。 // 只要至少有一个路径导致调用包装的http.RoundTripper,则装饰器可以执行几乎任何需要的操作。 func (m *timeoutRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { var ctx, cancel = context.WithTimeout(r.Context(), m.after) defer cancel() return m.Wrapped.RoundTrip(r.WithContext(ctx)) } // 所有配置都定义为结构体。结构体的每个字段对应配置中的一个设置。各个设置的名称绑定到结构体字段名。 // 可以为结构体字段添加可选的描述注释,在打印帮助文本时会显示。 type TimeoutConfig struct { After time.Duration `description:"请求取消前的持续时间。"` } // 还可以为结构体定义可选的Name()方法,该方法将更改用于标识配置部分根的键。默认情况下,键将与结构体名称匹配。 // 例如,如果删除此方法,系统将期望以下形式的配置: // // timeoutconfig: // after: "200ms" // // 而有此方法时: // // timeout: // after: "200ms" func (*TimeoutConfig) Name() string { return "timeout" } // 每个组件还需要一些与插件系统配合的脚手架。脚手架必须是结构体,但结构体不需要以结构体字段的形式维护任何状态。 // 不过,如果需要,可以使用结构体存储构造函数中提供的详细信息,如活动HTTP路径或方法。 type TimeoutComponent struct{} // 每个组件结构体需要一个构造函数才能安装在插件列表中。构造函数签名从项目导出为transportd.NewComponent,与下面的方法匹配。 // 如果组件需要了解提供的任何值,则可以将这些值存储在组件结构体上。 func Timeout(ctx context.Context, backend string, path string, method string) (interface{}, error) { return &TimeoutComponent{}, nil } // 作为插件系统的一部分,组件结构体必须定义一个名为'Settings()'的方法,该方法返回配置结构体的指针实例。 // 实例应填充任何默认值,这些值将同时用作默认值和帮助文本中显示的值。 func (*TimeoutComponent) Settings() *TimeoutConfig { return &TimeoutConfig{After: defaultTimeoutSettingAfter} } // 组件的最后一部分是要安装的中间件的构造函数。构造函数必须名为'New',第一个参数必须是context.Context, // 第二个参数必须与'Settings()'方法返回的类型相同。返回值必须与此示例匹配。 func (*TimeoutComponent) New(_ context.Context, conf *TimeoutConfig) (func(http.RoundTripper) http.RoundTripper, error) { // nolint // 上下文对象保证包含指向原始openapi3.Swagger文档的指针。如果组件需要此指针,应将命名函数参数中的`_`更改为`ctx`,并使用: // ctx.Value(transportd.ContextKeyOpenAPISpec.String("doc")).(*openapi3.Swagger) return func(next http.RoundTripper) http.RoundTripper { return &timeoutRoundTripper{RoundTripper: next, after: conf.After} }, nil }
创建自定义构建相当于将此项目的main.go复制到您自己的仓库中,并将任何已构建的自定义组件添加到列表中:
golangpackage main import ( "context" "flag" "fmt" "io" "os" transportd "github.com/asecurityteam/transportd/pkg" "github.com/asecurityteam/transportd/pkg/components" ) func main() { ctx := context.Background() plugins := []transportd.NewComponent{ components.Metrics, components.AccessLog, components.ASAPValidate, components.ValidateHeaders, components.Timeout, components.Hedging, components.Retry, components.ASAPToken, components.RequestValidation, components.ResponseValidation, components.Strip, // 在此处插入任何自定义组件 // 顺序无关紧要,因为安装顺序由每个路径配置决定 } // 处理-h标志并打印设置 fs := flag.NewFlagSet("", flag.ContinueOnError) fs.Usage = func() {} err := fs.Parse(os.Args[1:]) if err == flag.ErrHelp { help, errHelp := transportd.Help(ctx, plugins...) if
您可以使用以下命令拉取该镜像。请将 <标签> 替换为具体的标签版本。如需查看所有可用标签版本,请访问 标签列表页面。
来自真实用户的反馈,见证轩辕镜像的优质服务