ousaa / sites-diversion-package
description
Package info
gitlab.seastt.com/ousaa/sites-diversion-package
pkg:composer/ousaa/sites-diversion-package
Requires
- php: >=7.4
- ext-json: *
- ext-redis: *
- topthink/framework: 5.1.*|^6.0|^8.0
Requires (Dev)
- phpunit/phpunit: ^9.6
README
依赖tp框架(支持版本5.1/6/8)
环境变量配置
单系统(默认)
站点只接入一个分流系统时,使用以下环境变量(与分流管理系统保持一致):
# 分流 Redis 连接配置
DIVERSION_REDIS_HOST=127.0.0.1
DIVERSION_REDIS_PORT=6379
DIVERSION_REDIS_PASSWORD=
DIVERSION_REDIS_DB=0
# Redis key 前缀,留空时默认使用 diversion:
DIVERSION_REDIS_PREFIX=
多系统同时接入
站点需要同时接入多个分流系统时,每个系统使用独立的环境变量前缀。前缀格式为 {SYSTEM_NAME}_DIVERSION_REDIS_*(系统名全大写):
# 系统一:默认分流系统(diversion-manager),无前缀
DIVERSION_REDIS_HOST=127.0.0.1
DIVERSION_REDIS_PORT=6379
DIVERSION_REDIS_PASSWORD=
DIVERSION_REDIS_DB=0
DIVERSION_REDIS_PREFIX=
# 系统二:ads-data 分流系统,前缀 ADS_DATA
ADS_DATA_DIVERSION_REDIS_HOST=127.0.0.1
ADS_DATA_DIVERSION_REDIS_PORT=6379
ADS_DATA_DIVERSION_REDIS_PASSWORD=
ADS_DATA_DIVERSION_REDIS_DB=0
ADS_DATA_DIVERSION_REDIS_PREFIX=ads_data
分流管理系统侧配置(自动识别)
分流管理系统(如 ads-data)本身不需要在代码里调用 setSystem(),只需在其 .env 中设置系统名:
DIVERSION_SYSTEM=ADS_DATA
包在读写 Redis 时会自动读取该环境变量,使用对应前缀的配置。
接入逻辑代码参考(兼容 tp5.1/6/8)
在 route/route.php(tp 6/8 是 route/app.php)文件中,实际业务路由注册之前添加以下代码。该方法命中分流目标时立即响应跳转,未命中或发生任何异常(如 Redis 连接失败)时自动跳过分流,继续执行后续业务路由。
\Ousaa\SitesDiversionPackage\RouteSetting::handle();
当前版本按当前请求 Host 自动匹配分流配置,不再支持通过参数单独指定某个域名处理。
多系统场景:手动指定系统
若当前站点需要在运行时动态切换分流系统(例如根据请求 Host 决定走哪套分流配置),可在调用 handle() 前显式设置系统名:
// 切换到 ads-data 分流系统(读取 ADS_DATA_DIVERSION_REDIS_* 配置)
\Ousaa\SitesDiversionPackage\RouteSetting::setSystem('ADS_DATA');
\Ousaa\SitesDiversionPackage\RouteSetting::handle();
setSystem() 的优先级高于 DIVERSION_SYSTEM 环境变量。系统名与环境变量前缀的对应关系:
| setSystem() 参数 | 读取的环境变量前缀 |
|---|---|
'default'(或不调用) | 无前缀,读取 DIVERSION_REDIS_* |
'ADS_DATA' | ADS_DATA_DIVERSION_REDIS_* |
'FOO_BAR' | FOO_BAR_DIVERSION_REDIS_* |
处理结果与后续执行逻辑
handle() 处理后有三个关键结果维度:
- 本系统是否跳转:命中并产生跳转响应时请求立即终止(抛出
HttpResponseException/ 直接响应),后续业务路由与其他系统都不再执行。 $handled锁定状态:决定后续再次调用handle()(通常是setSystem()切换到另一系统后)是否会真正处理。锁定 = 后续handle()直接跳过;解锁 = 后续handle()会重新处理同一请求。- 后续业务路由是否继续执行:只要本系统没有产生跳转,请求都会继续走
handle()之后注册的原有业务路由。
「命中」= 当前请求 Host+URI 在本系统分流配置中存在(无论分流跳转、命中不分流、还是命中但无目标);「未命中」= 本系统无对应配置或处理异常(如 Redis 连接失败)。
default 系统(处理过一次后,无论结果如何都保持锁定,保持原有逻辑):
| 场景 | 本系统是否跳转 | $handled 锁定状态 | 后续业务路由 |
|---|---|---|---|
| 未命中(无配置) | 否 | 锁定(后续 handle() 跳过) | 继续执行 |
| 命中 → 分流跳转(含一次性跳转 / defaultLink 兜底成功) | 是,请求终止 | —(请求已终止) | 不执行 |
| 命中 → 不分流(is_not_diversion=1) | 否(仅累计统计) | 锁定 | 继续执行 |
| 命中 → 无目标且无 defaultLink 兜底 | 否 | 锁定 | 继续执行 |
| 处理异常(Redis 连接失败等) | 否 | 锁定 | 继续执行 |
非 default 系统(仅「未命中/异常」时解锁,让后续系统有机会处理同一请求;一旦命中即认领并锁定):
| 场景 | 本系统是否跳转 | $handled 锁定状态 | 后续业务路由 |
|---|---|---|---|
| 未命中(无配置) | 否 | 解锁(后续切换系统再调用 handle() 会重新处理) | 继续执行 |
| 命中 → 分流跳转(含一次性跳转 / defaultLink 兜底成功) | 是,请求终止 | —(请求已终止) | 不执行 |
| 命中 → 不分流(is_not_diversion=1) | 否(仅累计统计) | 保持锁定(已认领,后续 handle() 跳过) | 继续执行 |
| 命中 → 无目标且无 defaultLink 兜底 | 否 | 保持锁定(已认领) | 继续执行 |
| 处理异常(Redis 连接失败等) | 否 | 解锁(按未命中处理,让后续系统继续尝试) | 继续执行 |
典型多系统接入用法(ADS_DATA 未命中 → 解锁 → default 接着处理):
\Ousaa\SitesDiversionPackage\RouteSetting::setSystem('ADS_DATA');
\Ousaa\SitesDiversionPackage\RouteSetting::handle(); // 未命中则解锁,命中则认领并锁定
\Ousaa\SitesDiversionPackage\RouteSetting::setSystem(); // 切回 default
\Ousaa\SitesDiversionPackage\RouteSetting::handle(); // default 处理,处理后始终锁定
// ...此处之后是原有业务路由,未跳转时正常执行
注意:多系统接入必须统一走
RouteSetting::handle()。旧入口controller\RouteController直接调用底层服务,不经过$handled锁与认领逻辑,多系统场景下不要使用。
调试模式
调试默认关闭。在调用 handle() 前通过 setDebug() 开启后,会把分流处理全过程详细写入日志(tp 框架 Log,debug 级别,渠道前缀 [sites-diversion-package][debug]):当前访问信息、由哪个系统处理、是否命中、命中目标、分流还是不分流、是否走 defaultLink 兜底、当前系统是否跳过、后续系统是否还会处理等。
\Ousaa\SitesDiversionPackage\RouteSetting::setDebug(); // 开启调试
\Ousaa\SitesDiversionPackage\RouteSetting::setDebug(false); // 关闭调试(默认)
\Ousaa\SitesDiversionPackage\RouteSetting::handle();
多系统场景下日志会带上 system=[系统名] 前缀,便于按系统关联整条处理链路。仅排查问题时临时开启,生产环境建议关闭以免日志量过大。
容错机制
- Redis 连接失败:自动跳过分流,继续走原有路由,不影响站点正常访问。错误信息通过 tp 框架的 Log 写入
error级别日志(渠道sites-diversion-package)。 - defaultLink 未配置:返回 null,请求继续走原有路由,不返回 404。
如果需要修改这个包的内容,可以改成本地调试
在 composer.json 里面添加,url 改成你本地对应目录的绝对路径
"repositories": [
{
"type": "path",
"url": "/Volumes/code/php_package/sites-diversion-package",
"options": {
"symlink": true
}
}
],
包的版本配置改成 dev-master
"ousaa/sites-diversion-package": "dev-master"
然后更新即可
composer update ousaa/sites-diversion-package
修改和调试完成之后,发布 ousaa/sites-diversion-package 的版本。然后删除 composer.json 里面 repositories 的部分, dev-master 改成最新版本即可