PHP开发API网关思路

wen PHP项目 1

本文目录导读:

PHP开发API网关思路

  1. 核心架构设计
  2. 核心实现代码
  3. 高级特性
  4. 部署与运维

我来给你一套PHP开发API网关的完整思路,从架构设计到具体实现。

核心架构设计

整体架构

客户端 → API网关 → 微服务集群
              ↓
        认证/限流/路由/日志

目录结构

api-gateway/
├── public/
│   └── index.php          # 入口文件
├── src/
│   ├── Core/
│   │   ├── Router.php     # 路由分发
│   │   ├── Handler.php    # 处理器链
│   │   └── Response.php   # 响应处理
│   ├── Middleware/
│   │   ├── Auth.php       # 认证中间件
│   │   ├── RateLimit.php  # 限流中间件
│   │   ├── Logger.php     # 日志中间件
│   │   └── CORS.php       # 跨域处理
│   ├── Service/
│   │   ├── Proxy.php      # 服务转发
│   │   ├── LoadBalancer.php # 负载均衡
│   │   └── CircuitBreaker.php # 熔断器
│   └── Config/
│       └── routes.php     # 路由配置
└── composer.json

核心实现代码

入口文件

<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
use Gateway\Core\Router;
use Gateway\Core\Handler;
// 初始化配置
$config = require __DIR__ . '/../src/Config/routes.php';
// 创建路由
$router = new Router($config);
// 创建处理器链
$handler = new Handler($router);
$handler->addMiddleware(new \Gateway\Middleware\CORS());
$handler->addMiddleware(new \Gateway\Middleware\Logger());
$handler->addMiddleware(new \Gateway\Middleware\Auth());
$handler->addMiddleware(new \Gateway\Middleware\RateLimit());
// 处理请求
$handler->handle();

路由核心

<?php
namespace Gateway\Core;
class Router {
    private $routes = [];
    private $services = [];
    public function __construct($config) {
        $this->routes = $config['routes'] ?? [];
        $this->services = $config['services'] ?? [];
    }
    public function route() {
        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        $method = $_SERVER['REQUEST_METHOD'];
        foreach ($this->routes as $pattern => $route) {
            if ($this->match($pattern, $path, $matches)) {
                return [
                    'service' => $route['service'],
                    'path' => $this->buildTargetPath($route, $matches),
                    'method' => $method
                ];
            }
        }
        return null;
    }
    private function match($pattern, $path, &$matches) {
        $pattern = preg_replace('/\{[^\/]+\}/', '([^\/]+)', $pattern);
        $pattern = str_replace('/', '\/', $pattern);
        return preg_match("/^{$pattern}$/", $path, $matches);
    }
    private function buildTargetPath($route, $matches) {
        $path = $route['path'] ?? '';
        array_shift($matches);
        foreach ($matches as $value) {
            $path = preg_replace('/\{[^\/]+\}/', $value, $path, 1);
        }
        return $path;
    }
}

处理器链

<?php
namespace Gateway\Core;
class Handler {
    private $middleware = [];
    private $router;
    public function __construct($router) {
        $this->router = $router;
    }
    public function addMiddleware($middleware) {
        $this->middleware[] = $middleware;
        return $this;
    }
    public function handle() {
        // 创建请求对象
        $request = new Request();
        $response = new Response();
        // 创建处理链
        $next = function() use ($response) {
            return $response;
        };
        // 反向遍历中间件
        $middlewares = array_reverse($this->middleware);
        foreach ($middlewares as $middleware) {
            $next = function() use ($middleware, $request, $next) {
                return $middleware->process($request, $next);
            };
        }
        // 执行处理链
        $result = $next();
        // 输出响应
        $result->send();
    }
}

服务转发(代理)

<?php
namespace Gateway\Service;
class Proxy {
    private $httpClient;
    public function forward($request, $targetService) {
        $url = $this->buildUrl($targetService, $request->getPath());
        $options = [
            'http' => [
                'method' => $request->getMethod(),
                'header' => $this->buildHeaders($request),
                'content' => $request->getContent(),
                'timeout' => 5,
                'ignore_errors' => true
            ]
        ];
        // 使用多线程处理并发请求
        return $this->asyncRequest($url, $options);
    }
    private function buildUrl($service, $path) {
        // 结合负载均衡策略选择实例
        $instance = LoadBalancer::select($service);
        return "http://{$instance['host']}:{$instance['port']}{$path}";
    }
    private function asyncRequest($url, $options) {
        $shared = [];
        $client = curl_init();
        curl_setopt_array($client, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_FOLLOWLOCATION => true,
        ]);
        // 使用Swoole或ReactPHP实现真正的异步
        return $this->executeAsync($client);
    }
}

认证中间件

<?php
namespace Gateway\Middleware;
use Firebase\JWT\JWT;
class Auth {
    private $jwtSecret = 'your-secret-key';
    public function process($request, $next) {
        // 获取token
        $token = $this->extractToken($request);
        if (!$token) {
            return new \Gateway\Core\Response(401, ['error' => 'Unauthorized']);
        }
        // 验证JWT
        try {
            $payload = JWT::decode($token, $this->jwtSecret, ['HS256']);
            $request->setUser($payload->user);
        } catch (\Exception $e) {
            return new \Gateway\Core\Response(401, ['error' => 'Token invalid']);
        }
        // 权限检查
        $route = $request->getRoute();
        if (!$this->checkPermission($payload->user, $route)) {
            return new \Gateway\Core\Response(403, ['error' => 'Forbidden']);
        }
        // 传递给下一个中间件
        return $next($request);
    }
}

限流中间件

<?php
namespace Gateway\Middleware;
use Predis\Client;
class RateLimit {
    private $redis;
    private $limit = 60; // 每分钟请求数
    private $window = 60; // 窗口时间(秒)
    public function __construct() {
        $this->redis = new Client([
            'scheme' => 'tcp',
            'host'   => '127.0.0.1',
            'port'   => 6379,
        ]);
    }
    public function process($request, $next) {
        $ip = $request->getClientIp();
        $key = "rate_limit:{$ip}";
        // 滑动窗口限流
        $current = $this->redis->incr($key);
        if ($current === 1) {
            $this->redis->expire($key, $this->window);
        }
        if ($current > $this->limit) {
            return new \Gateway\Core\Response(429, [
                'error' => 'Too Many Requests'
            ]);
        }
        return $next($request);
    }
}

熔断器

<?php
namespace Gateway\Service;
class CircuitBreaker {
    private $failureCount = 0;
    private $successCount = 0;
    private $threshold = 5;
    private $timeout = 30;
    private $state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    public function call($callback) {
        if ($this->state === 'OPEN') {
            if (time() > $this->lastOpenTime + $this->timeout) {
                $this->state = 'HALF_OPEN';
            } else {
                return $this->fallback();
            }
        }
        try {
            $result = $callback();
            $this->onSuccess();
            return $result;
        } catch (\Exception $e) {
            $this->onFailure();
            return $this->fallback();
        }
    }
}

配置中心

<?php
// src/Config/routes.php
return [
    'routes' => [
        '/user/\{id\}' => [
            'service' => 'user-service',
            'path' => '/users/{id}',
            'auth' => true,
            'permission' => 'user.view'
        ],
        '/order/\{id\}' => [
            'service' => 'order-service',
            'path' => '/orders/{id}'
        ]
    ],
    'services' => [
        'user-service' => [
            'instances' => [
                ['host' => '192.168.1.1', 'port' => 8080],
                ['host' => '192.168.1.2', 'port' => 8080]
            ],
            'load_balance' => 'round_robin'
        ],
        'order-service' => [
            'instances' => [
                ['host' => '192.168.2.1', 'port' => 8081]
            ]
        ]
    ]
];

高级特性

使用Swoole实现高性能

// swoole_server.php
use Swoole\Http\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;
$server = new Server("0.0.0.0", 9501);
$server->on("start", function ($server) {
    echo "Gateway started\n";
});
$server->on("request", function (Request $request, Response $response) {
    // 处理请求
    $handler = new Gateway\Core\Handler(new Router($config));
    $result = $handler->handleAsync($request);
    $response->header("Content-Type", "application/json");
    $response->end(json_encode($result));
});
$server->start();

使用Redis做服务发现

<?php
namespace Gateway\Service;
class ServiceDiscovery {
    private $redis;
    public function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }
    public function getServiceInstances($serviceName) {
        // 服务注册表
        $key = "service:{$serviceName}";
        return $this->redis->hgetall($key);
    }
    public function register() {
        // 注册当前服务
    }
}

部署与运维

Docker部署

# docker-compose.yml
version: '3'
services:
  api-gateway:
    build: .
    ports:
      - "80:80"
    environment:
      - REDIS_HOST=redis
      - DB_HOST=mysql
    depends_on:
      - redis
      - mysql
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=secret

监控指标

<?php
// 添加统计中间件
class StatisticsMiddleware {
    public function process($request, $next) {
        $start = microtime(true);
        $response = $next($request);
        $duration = microtime(true) - $start;
        // 记录指标
        Metrics::record([
            'path' => $request->getPath(),
            'duration' => $duration,
            'status' => $response->getStatus(),
            'timestamp' => time()
        ]);
        return $response;
    }
}

这套架构已经涵盖API网关的核心功能,你可以根据业务需求选择相应的组件和实现方式,推荐使用Swoole或ReactPHP来提升并发处理能力。

抱歉,评论功能暂时关闭!