PHP项目多版本并存如何分流访问流量

wen PHP项目 23

本文目录导读:

PHP项目多版本并存如何分流访问流量

  1. 方案一:基于 Nginx 的 URI/Header/Cookie 分流(最推荐)
  2. 方案二:基于网关(APISIX/Kong)的分流
  3. 方案三:基于 PHP-FPM 多实例 + 项目目录隔离
  4. 方案四:基于 Docker/K8s 的 Service Mesh
  5. 方案五:基于 DNS 的简单分流(不推荐)
  6. 总结建议

针对 PHP 项目多版本并存的分流需求,核心目标通常是灰度发布A/B测试平滑升级,实现方案主要分为三大类:网关层分流负载均衡层分流应用层/容器层分流

以下是几种经过生产验证的成熟方案,按推荐程度排序:

基于 Nginx 的 URI/Header/Cookie 分流(最推荐)

这是最灵活、性能最高的方案,不依赖业务代码,直接在入口层完成分发。

适用场景:

  • 灰度发布(让部分用户先体验新版)
  • A/B 测试(根据 User-Agent、Cookie 等特征分流)

基本配置示例(Nginx):

upstream old_php {
    server 127.0.0.1:9000;  # 老版本 PHP-FPM
}
upstream new_php {
    server 127.0.0.1:9001;  # 新版本 PHP-FPM
}
server {
    listen 80;
    server_name example.com;
    location / {
        # 条件1:根据 Cookie 分流(如灰度用户标记)
        if ($http_cookie ~* "version=new") {
            set $php_backend "new_php";
        }
        # 条件2:根据 IP 分流(测试人员)
        if ($remote_addr ~* "192.168.1.100") {
            set $php_backend "new_php";
        }
        # 默认走老版本
        if ($php_backend = "") {
            set $php_backend "old_php";
        }
        # 动态传递到对应版本的 PHP-FPM
        fastcgi_pass $php_backend;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    }
}

高级用法(权重分流):

split_clients "${remote_addr}${http_user_agent}" $version_tag {
    10%   "new";  # 10% 流量走新版
    *     "old";  # 其余走旧版
}
location / {
    if ($version_tag = "new") {
        fastcgi_pass 127.0.0.1:9001;
    }
    fastcgi_pass 127.0.0.1:9000;
}

优点:对应用透明,性能损耗极小。
缺点:需要 Nginx 重启或 reload。


基于网关(APISIX/Kong)的分流

适用于微服务架构,或需要动态调整分流规则而不重启服务的场景。

以 Apache APISIX 为例:
可以通过 traffic-split 插件实现。

# 路由配置
- uri: /api/v1/*
  upstream_id: old-upstream-id
  plugins:
    traffic-split:
      rules:
        - weighted_upstreams:
            - upstream:
                name: new-version-upstream
                nodes:
                  "127.0.0.1:9001": 1
              weight: 10  # 10% 流量
        - # 剩下的 90% 自动走默认 upstream

优点:可动态调整比例(无需重启)、支持请求重放、支持金丝雀发布。
缺点:需要引入额外组件,运维复杂度稍高。


基于 PHP-FPM 多实例 + 项目目录隔离

适用于同一个代码库但需运行不同版本 PHP(如 PHP 7.4 和 PHP 8.2)。

步骤:

  1. 启动两个 PHP-FPM 实例(监听不同端口)。
# 启动 PHP 7.4
/usr/sbin/php-fpm7.4 --fpm-config /etc/php/7.4/fpm/php-fpm.conf -p /var/run/php7.4/
# 启动 PHP 8.2
/usr/sbin/php-fpm8.2 --fpm-config /etc/php/8.2/fpm/php-fpm.conf -p /var/run/php8.2/
  1. 项目目录独立

    • /var/www/old_project/ → 指向 PHP 7.4 版本代码
    • /var/www/new_project/ → 指向 PHP 8.2 版本代码(或同一代码但不同分支)
  2. Nginx 配置(按域名/路径分发)

server {
    listen 80;
    server_name old.example.com;
    root /var/www/old_project;
    fastcgi_pass 127.0.0.1:9000;
}
server {
    listen 80;
    server_name new.example.com;
    root /var/www/new_project;
    fastcgi_pass 127.0.0.1:9001;
}

基于 Docker/K8s 的 Service Mesh

适合容器化、Kubernetes 环境,利用 Istio 或 Linkerd 进行精细流量治理。

核心思路(K8s + Istio):

  • 部署两个 Deploymentphp-v1(旧版)、php-v2(新版)
  • 通过 VirtualService 定义权重路由:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: php-service
spec:
  hosts:
  - php-service
  http:
  - match:
    - headers:
        x-version:
          exact: v2
    route:
    - destination:
        host: php-service
        subset: v2
  - route:
    - destination:
        host: php-service
        subset: v1
      weight: 90
    - destination:
        host: php-service
        subset: v2
      weight: 10

优点:完全声明式、天然支持弹性伸缩、可观测性强。
缺点:需要完整 K8s 基础设施,投入较大。


基于 DNS 的简单分流(不推荐)

做法:配置不同二级域名指向不同服务器参数。

v1.app.com → 192.168.1.10 (旧版)
v2.app.com → 192.168.1.11 (新版)

适用:极简单的环境隔离(开发/测试/生产互不干扰)。
缺点:无法实现细粒度灰度,切换需要 DNS 生效时间。


总结建议

场景 推荐方案
单机/低并发 Nginx Cookie/IP 分流 + 多 PHP-FPM 进程
中大型微服务 APISIX / Kong 网关分流
容器化/K8s 环境 Istio + VirtualService 权重路由
只想测试新版本 单独域名 + Nginx proxy_pass 到不同后端
极简管理 通过 supervisor 管理多个 PHP-FPM + 软链接切换目录(不推荐生产)

注意事项:

  1. Session 共享:多版本分流时注意 Session 存储(建议使用 Redis),否则用户在不同版本间切换会丢失登录状态。
  2. 数据库兼容:旧版代码可能不支持新版数据库字段变更,建议先做只读灰度。
  3. 监控:务必监控两个版本对应的 PHP-FPM 进程的 max_children 和慢日志。

如果你能提供更多细节(如项目架构、是否容器化、并发量级),我可以给出更精确的配置示例。

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