用“幼儿园门卫室”比喻理解 Hyperf API 网关
1. 什么是 API 网关?
想象幼儿园的“门卫室”:
-
传统方式:家长要找不同的老师(服务),需要自己记住每个老师的教室位置,直接去找。
-
API 网关方式:
- 家长先到门卫室(API 网关),告诉门卫要找哪位老师;
- 门卫查“老师位置表”,告诉家长该去哪个教室,或者直接帮家长联系老师;
- 门卫还会检查家长身份(认证)、看看有没有带危险物品(限流)、记录来访时间(日志)。
这就是“API 网关”:
- 统一入口:所有请求都通过网关进入系统;
- 路由转发:根据请求路径转发到对应的服务;
- 功能增强:提供认证、限流、日志等通用功能。
2. 在 Hyperf 中搭建 API 网关包含哪些部分?
画一个“幼儿园门卫室系统”示意图:
┌───────────────────────────┐
│ API 网关系统 │
├───────────────────────────┤
│ 门卫室:网关服务器 │
│ ├─ 接收所有外部请求 │
│ └─ 转发请求到后端服务 │
│ │
│ 老师位置表:路由配置 │
│ ├─ 定义请求路径与服务的映射 │
│ └─ 支持动态路由 │
│ │
│ 身份核查员:认证中间件 │
│ ├─ 验证请求身份 │
│ └─ 权限检查 │
│ │
│ 流量控制员:限流中间件 │
│ ├─ 限制请求频率 │
│ └─ 防止恶意攻击 │
│ │
│ 记录员:日志中间件 │
│ ├─ 记录请求信息 │
│ └─ 统计分析 │
└───────────────────────────┘
3. 代码演示:在 Hyperf 中搭建 API 网关
下面是一个简单的 API 网关示例:
<?php
// 1. 路由配置(就像门卫的老师位置表)
// 文件名:config/routes.php
Router::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/api/{service}/{action}', function (ServerRequestInterface $request) {
// 获取请求的服务和动作
$service = $request->getAttribute('service');
$action = $request->getAttribute('action');
// 根据服务名查找对应的后端服务地址(这里简化为配置映射)
$serviceMap = [
'user' => 'http://user-service:9501',
'order' => 'http://order-service:9502',
'product' => 'http://product-service:9503',
];
// 如果找不到服务,返回404
if (!isset($serviceMap[$service])) {
return json_encode(['code' => 404, 'message' => 'Service not found']);
}
// 构建后端服务的URL
$backendUrl = "{$serviceMap[$service]}/{$action}";
// 转发请求到后端服务(就像门卫帮家长联系老师)
$client = new \GuzzleHttp\Client();
$response = $client->request(
$request->getMethod(),
$backendUrl,
[
'headers' => $request->getHeaders(),
'body' => $request->getBody(),
]
);
// 返回后端服务的响应
return $response->getBody();
});
// 2. 认证中间件(就像门卫检查家长身份)
// 文件名:app/Middleware/AuthMiddleware.php
class AuthMiddleware implements MiddlewareInterface {
public function process(ServerRequestInterface $request, MiddlewareHandlerInterface $handler): ResponseInterface {
// 从请求头中获取token
$token = $request->getHeaderLine('Authorization');
// 验证token(这里简化为检查是否有token)
if (empty($token)) {
$response = new Response();
return $response->withStatus(401)->withBody(new Stream('Unauthorized'));
}
// 验证通过,继续处理请求
return $handler->handle($request);
}
}
// 3. 限流中间件(就像门卫控制进入幼儿园的人数)
// 文件名:app/Middleware/RateLimitMiddleware.php
class RateLimitMiddleware implements MiddlewareInterface {
public function process(ServerRequestInterface $request, MiddlewareHandlerInterface $handler): ResponseInterface {
// 获取客户端IP(就像记住家长的脸)
$clientIp = $request->getServerParams()['remote_addr'] ?? 'unknown';
// 使用Redis记录请求次数(就像门卫用本子记录来访次数)
$redis = di()->get(\Redis::class);
$key = "rate_limit:{$clientIp}";
$count = $redis->incr($key);
// 设置过期时间(1分钟)
if ($count === 1) {
$redis->expire($key, 60);
}
// 如果请求次数超过限制(每分钟100次)
if ($count > 100) {
$response = new Response();
return $response->withStatus(429)->withBody(new Stream('Too Many Requests'));
}
// 未超过限制,继续处理请求
return $handler->handle($request);
}
}
// 4. 日志中间件(就像门卫记录来访信息)
// 文件名:app/Middleware/LogMiddleware.php
class LogMiddleware implements MiddlewareInterface {
public function process(ServerRequestInterface $request, MiddlewareHandlerInterface $handler): ResponseInterface {
// 记录请求信息(就像门卫记录家长姓名、来访时间)
$logger = di()->get(\Hyperf\Logger\LoggerInterface::class);
$logger->info(sprintf(
'Request: %s %s',
$request->getMethod(),
$request->getUri()
));
// 继续处理请求
$response = $handler->handle($request);
// 记录响应信息(就像门卫记录家长离开时间)
$logger->info(sprintf(
'Response: %s',
$response->getStatusCode()
));
return $response;
}
}
// 5. 配置中间件(就像给门卫安排工作)
// 文件名:config/autoload/middlewares.php
return [
'http' => [
App\Middleware\AuthMiddleware::class,
App\Middleware\RateLimitMiddleware::class,
App\Middleware\LogMiddleware::class,
],
];
4. API 网关背后到底做了哪些事情?
用“幼儿园门卫室”比喻:
请求进入时:
- 家长来到幼儿园门口,先到门卫室(请求到达 API 网关);
- 门卫检查家长身份(认证中间件验证 token);
- 门卫看看今天已经来了多少家长(限流中间件检查请求频率);
- 门卫在“老师位置表”上查找家长要找的老师(路由配置匹配服务);
- 门卫告诉家长去哪个教室,或者帮家长联系老师(转发请求到后端服务);
- 门卫记录家长的来访信息(日志中间件记录请求和响应)。
响应返回时:
- 老师的回复通过门卫转达给家长(后端服务响应通过网关返回);
- 门卫记录家长离开的时间(日志中间件记录响应时间)。
5. API 网关的使用场景
- 统一入口:所有外部请求通过网关进入系统,便于管理;
- 认证授权:集中处理身份验证和权限控制;
- 流量控制:限制请求频率,防止系统被压垮;
- 协议转换:将 HTTP 请求转换为内部服务使用的协议;
- 请求聚合:将多个服务的响应合并为一个响应返回;
- 灰度发布:控制新服务的访问比例,逐步推广。
思维导图:API 网关
┌───────────────────┐
│ API 网关 │
│ (幼儿园门卫室) │
├───────────────────┤
│ 核心组件: │
│ ├─ 网关服务器 │
│ ├─ 路由配置 │
│ ├─ 认证中间件 │
│ ├─ 限流中间件 │
│ └─ 日志中间件 │
│ │
│ 工作流程: │
│ 1. 接收请求 │
│ 2. 认证授权 │
│ 3. 流量控制 │
│ 4. 路由转发 │
│ 5. 返回响应 │
│ │
│ 使用场景: │
│ ├─ 统一入口 │
│ ├─ 认证授权 │
│ ├─ 流量控制 │
│ └─ 协议转换 │
└───────────────────┘
流程图:API 网关工作流程
外部请求 → 网关服务器 → 认证中间件 → 限流中间件 → 路由配置 →
↓ ↑
后端服务 ←────────────────────────────────┘
概念图:API 网关的关系
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 外部请求 │───→│ API 网关 │───→│ 后端服务 │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ ↓
┌─────────────┐ │ ┌─────────────┐ ┌─────────────┐
│ 认证中间件 │←───┘ │ 路由配置 │←───│ 服务注册中心│
└─────────────┘ └─────────────┘ └─────────────┘
│
│
┌─────────────┐ │ ┌─────────────┐
│ 限流中间件 │←───┘ │ 日志中间件 │
└─────────────┘ └─────────────┘
总结:API 网关是微服务的“门卫室”
API 网关就像幼儿园的“门卫室”:
- 统一入口:所有外部请求都通过网关进入系统,就像所有家长都要经过门卫室;
- 功能增强:网关提供认证、限流、日志等通用功能,就像门卫检查身份、控制流量、记录信息;
- 路由转发:网关根据请求路径转发到对应的服务,就像门卫根据“老师位置表”指引家长。
有了 API 网关,微服务系统就能像有序的幼儿园一样,即使有很多老师和家长,也能通过门卫室高效管理!