API Gateway 部署
api-gateway 是 Firefly 裸机场景下的 north-south API 网关控制面。它消费 Consul 中按 namespace 隔离的 route document、健康 endpoint 和 descriptor current,生成入口 Envoy xDS。它与 api-gateway-envoy、sidecar-agent 和服务间透明导流的完整关系见 流量拓扑。
api-gateway 不负责签发 token、不做接口权限判断、不托管 Envoy / Consul 进程,也不替代旧 http-gateway 或旧 grpc-gateway。
运行入口
cd firefly/golang/api-gateway
go run ./cmd/server -config conf/bootstrap.json源码默认监听管理端口;本机访问可使用 127.0.0.1:18610:
0.0.0.0:18610源码默认监听 xDS gRPC 地址;Envoy Docker bootstrap 通过 host.docker.internal:18611 访问:
0.0.0.0:18611默认入口 Envoy listener:
0.0.0.0:18504Envoy 需要通过 ADS 访问 xds.listen_address,入口流量监听地址由 xds.listener_address 描述。
配置要点
conf/bootstrap.json 的关键段落:
{
"admin": {
"listen_address": "0.0.0.0:18610"
},
"xds": {
"listen_address": "0.0.0.0:18611",
"node_id": "api-gateway-envoy",
"listener_address": "0.0.0.0:18504",
"route_name": "api-gateway-route"
},
"envoy": {
"admin_address": "127.0.0.1:18505"
},
"consul": {
"address": "192.168.1.100:18500",
"datacenter": "dc1",
"refresh_interval": "30s"
},
"authz": {
"service_name": "authz",
"service_namespace": "lhdht",
"timeout": "200ms"
},
"namespaces": [
{
"name": "lhdht",
"descriptor_current_key": "lhdht/api-gateway/descriptor/current",
"routes_prefix": "lhdht/routes"
},
{
"name": "story-studio",
"descriptor_current_key": "story-studio/api-gateway/descriptor/current",
"routes_prefix": "story-studio/routes"
}
]
}本机开发时可以按环境把 consul.address 改成 127.0.0.1:18500;以实际部署的 conf/bootstrap.json 为准。
authz.service_name 和 authz.service_namespace 用来计算 Envoy ext_authz 要调用的普通服务 cluster。authz 没有健康实例时,下发空 EDS,Envoy 按 fail-close 处理。
与 api-gateway-envoy 的关系
api-gateway 只控制 api-gateway-envoy,不控制 sidecar-agent-envoy。当前 Envoy bootstrap 中 node.id 为 api-gateway-envoy,静态 xDS cluster 连接宿主机 host.docker.internal:18611;Compose 对宿主机发布 18504 north-south 数据面入口和 18505 admin。
api-gateway-envoy 额外只读挂载 /opt/store/api-gateway/bin/var/data/descriptor,用于读取 gRPC-JSON transcoder 所需 descriptor。该目录由宿主机上的 api-gateway 进程维护。
Namespace Descriptor
HTTP/JSON 转 gRPC 所需 descriptor 由 proto 项目发布。proto 项目的 .firefly/project.yaml 必须使用:
project:
type: proto发布命令:
firefly descriptor publish发布后,Consul KV 中的 descriptor current key 形如:
{namespace}/api-gateway/descriptor/current例如:
lhdht/api-gateway/descriptor/current
story-studio/api-gateway/descriptor/currentapi-gateway 会按 namespace 拉取 descriptor current JSON,下载并校验对应 pb。不同 proto 仓库生成的 descriptor 不会被合并成一份全局 pb,转码 route 通过 route-level typed per-filter config 绑定自己的 namespace descriptor。
descriptor 不只需要能解析成 google.protobuf.FileDescriptorSet,还必须包含 route document 中转码 route 声明的 grpc_service。如果 descriptor 缺少目标 proto service,api-gateway 会拒绝发布新 xDS 并在 /debug/xds.snapshot_error 暴露错误,避免把必然被 Envoy RDS NACK 的配置下发给 api-gateway-envoy。
Route Document
入口路由来自 Consul 中按 namespace 隔离的 route document:
{namespace}/routes/{service_app_id}/current规则:
protocol=grpc:exact_paths[]表示 gRPC 入口事实。http_routes[]:表示 HTTP/JSON -> gRPC 转码入口,full_method必须属于exact_paths[]。- 转码 route 使用该 route 所属 namespace 的 descriptor current,不再要求业务服务携带 descriptor 引用;descriptor current 必须覆盖该 route 的 proto service。
protocol=http:表示原生 HTTP proxy,不携带exact_paths[]或full_method。
api-gateway 会把 route document 的 app_id 写入 Envoy ext_authz context_extensions.app_id,authz 内部再映射为 target_app_id。
调试接口
curl http://127.0.0.1:18610/healthz
curl http://127.0.0.1:18610/readyz
curl http://127.0.0.1:18610/debug/runtime
curl http://127.0.0.1:18610/debug/namespaces
curl http://127.0.0.1:18610/debug/namespaces/lhdht/routes
curl http://127.0.0.1:18610/debug/namespaces/lhdht/descriptor
curl http://127.0.0.1:18610/debug/consul
curl http://127.0.0.1:18610/debug/descriptors
curl http://127.0.0.1:18610/debug/xds
curl http://127.0.0.1:18610/debug/envoy
curl -X POST http://127.0.0.1:18610/debug/reload排障顺序建议:
- 先看
/debug/runtime和/readyz。 - 再看
/debug/namespaces、/debug/consul、/debug/xds、/debug/envoy。 - 最后检查 route document、descriptor current、Consul 服务名和 authz 服务连接;若
/debug/xds.snapshot_error提示 service 不在 descriptor 中,先重新发布 namespace descriptor current。
上线前检查
- Envoy、Consul 已由基础设施层启动,api-gateway 能访问 Envoy admin 与 Consul HTTP API。
namespaces[]已声明目标 namespace、route prefix 和 descriptor current key。- 对应 namespace 的 proto 项目已发布 descriptor current,且
/debug/descriptors中的grpc_services覆盖所有转码 route。 - 业务服务已生成并上报
gateway.manifest.json,sidecar-agent 已写入 route document。 - authz / Casbin 策略已区分 HTTP 绑定和 gRPC 绑定。
- Trace 传播使用
traceparent、tracestate和baggage。