Traefik 中 EntryPoint 和Router 以及Service 三者之间的关系
·
三种对象形成一条严格的请求处理链:
客户端请求 → EntryPoint → Router → Service → 后端服务器
各自职责
| 对象 | 类比 | 职责 |
|---|---|---|
| EntryPoint | 小区大门 | 监听端口、接收网络包,决定用 TCP 还是 HTTP 协议 |
| Router | 前台接待 | 检查请求特征(域名、路径、Header),决定"谁来处理这个请求" |
| Service | 分配任务的经理 | 决定"把请求转发给哪个后端",以及如何负载均衡 |
组合关系:一个完整示例
假设你有一个电商系统,对外暴露两个端口:
互联网
│
├── :443 (HTTPS EntryPoint "websecure")
│ │
│ ├── Router "dashboard" 域名=dashboard.example.com
│ │ └── Service "dashboard-svc" → 10.0.1.5:3000
│ │
│ ├── Router "api" 域名=api.example.com
│ │ └── Service "api-svc" → 10.0.1.10:8080, 10.0.1.11:8080 (负载均衡)
│ │
│ └── Router "shop" 域名=shop.example.com
│ └── Service "shop-svc" → 10.0.1.20:3000
│
└── :9000 (TCP EntryPoint "mysql")
│
└── Router "mysql-route" HostSNI=*.db.example.com
└── Service "mysql-svc" → 10.0.2.1:3306
关键关系:
- 一个 EntryPoint 可以挂多个 Router(
:443上挂了 3 个 HTTP Router) - 一个 Router 只能指向一个 Service,但一个 Service 可以包含多个后端实例
- Router 通过规则匹配连接到 EntryPoint 上的特定请求流
代码层面怎么看
用 Traefik 的静态配置 + 动态配置来看这个过程:
Let me also look at how the three concepts connect in the server code to show the relationship.
Let me read a broader section of the BuildHandlers function to show how EntryPoint → Router → Service chain is built in code.
Now let me also check how routers connect to services. Let me find the buildEntryPointHandler function.
代码中的实际组装过程
从 pkg/server/router/router.go 可以看到,三者的关系在代码里是这样建立的:
BuildHandlers()
│
├── 1. 获取每个 EntryPoint 下挂的所有 Router
│ m.getHTTPRouters(ctx, entryPoints, tls)
│
└── 2. 为每个 EntryPoint 构建 Handler
buildEntryPointHandler()
│
├── 创建 Muxer(HTTP 路由表)
│
├── 遍历该 EntryPoint 下的每个 Router
│ │
│ ├── buildRouterHandler() → 根据 Router.Service 找到对应的 Service
│ │ → 组装 Middleware 链
│ │ → 返回最终 handler
│ │
│ └── muxer.AddRoute(router.Rule, handler) → 把规则+处理器注册到 Muxer
│
└── 返回 Muxer 作为该 EntryPoint 的 HTTP Handler
一个具体的 Docker 部署示例
# 静态配置:定义 EntryPoint
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
# 动态配置(file provider):定义 Router → Service 映射
http:
routers:
# Router "dashboard" 挂在 websecure 入口上
dashboard:
entryPoints: ["websecure"] # ← 指定绑在哪个 EntryPoint
rule: "Host(`dashboard.example.com`)" # ← 匹配规则
service: dashboard-svc # ← 指向哪个 Service
middlewares: ["auth@file"] # ← 可选的中间件链
tls: {}
api-router:
entryPoints: ["websecure"]
rule: "Host(`api.example.com`) && PathPrefix(`/v1`)"
service: api-svc
services:
dashboard-svc:
loadBalancer:
servers:
- url: "http://10.0.1.5:3000"
api-svc:
loadBalancer:
servers:
- url: "http://10.0.1.10:8080"
- url: "http://10.0.1.11:8080"
healthCheck: # 健康检查
path: /health
middlewares:
auth:
basicAuth:
users:
- "admin:$2y$05$..."
一次请求的完整链路:
curl https://api.example.com/v1/users
1. EntryPoint "websecure" (:443)
→ TLS 终止,得到 HTTP 请求 "GET /v1/users Host: api.example.com"
2. Router "api-router"
→ 规则匹配成功: Host==api.example.com && PathPrefix==/v1 ✓
→ 选定 Service: api-svc
3. Service "api-svc"
→ 从 [10.0.1.10:8080, 10.0.1.11:8080] 中选一个(WRR 算法)
→ 转发请求到后端
核心要点
| 关系 | 说明 |
|---|---|
| EntryPoint → Router | 一对多,一个端口可以服务多个域名 |
| Router → Service | 一对一,每个 Router 精确指向一个 Service |
| Service → Backend | 一对多,一个 Service 下可以挂多个后端实例做负载均衡 |
| Router → Middleware | 一对多,Router 可选地串联多个中间件(auth、限流、重写等) |
三者就像流水线上的三个工位:EntryPoint 负责接包,Router 负责分流,Service 负责分发。
更多推荐



所有评论(0)