本文目录导读:

在 PHP 项目中统计长短传比例分布,通常有两种截然不同的场景,需要根据你的“长短传”具体指代来选择方案。
场景 A:指 HTTP/网络请求中的长短连接(Keep-Alive) 这是最常见的情况,用于性能分析或负载均衡决策。
场景 B:指业务数据中的长短文本(如评论、文章、字段内容)分析或数据库优化。
以下是针对这两种场景的详细统计与可视化方案:
场景 A:统计 HTTP 长短连接(请求耗时/连接时长)分布
在 PHP(尤其是常驻内存的 Swoole、Workerman 或 FPM)中,通常通过请求耗时来间接判断连接长短,长连接通常意味着长轮询或流式传输。
数据采集(中间件或钩子)
使用框架中间件(如 Laravel/Tp 的中间件)或 Swoole 的 onRequest 回调记录连接参数。
// 示例:使用 Laravel 中间件统计请求耗时
class RequestDurabilityMiddleware {
public function handle($request, Closure $next) {
$start = microtime(true);
$response = $next($request);
$duration = (microtime(true) - $start) * 1000; // 毫秒
// 存入 Redis 或日志,或者打点上报
Log::channel('long_short_ratio')->info('', [
'duration_ms' => $duration,
// 这里加入你的判定逻辑,>1000ms 算长连接
'type' => $duration > 1000 ? 'long' : 'short',
]);
return $response;
}
}
聚合统计(使用 Redis 计数器)
在 Redis 中维护两个计数器,或者在日志中按阈值分组。
// 假设你有一个 Cron 任务每小时跑一次,统计近1小时的数据
$logs = collect(Log::channel('long_short_ratio')->get());
$longCount = $logs->where('type', 'long')->count();
$shortCount = $logs->where('type', 'short')->count();
$total = $longCount + $shortCount;
$longPercentage = round(($longCount / $total) * 100, 2);
可视化(生成图表)
使用 Chart.js 在前端展示饼图或柱状图,你只需要提供一个 JSON 接口。
// 返回 JSON 给前端
return response()->json([
'labels' => ['长连接', '短连接'],
'data' => [
'long' => $longCount,
'short' => $shortCount,
'long_percentage' => $longPercentage
]
]);
注意:对于真正的 TCP 长连接(如 WebSocket),PHP-FPM 场景下几乎不存在,需在 Swoole 等环境下通过
onClose回调统计连接存活时间。
场景 B:统计业务数据中的长文本/短文本比例
如果你是想统计数据库里某字段(如 content的比例(比如文章字数分布),可以按字节数或字符数分桶统计。
SQL 统计法(高效)
直接利用 MySQL 函数在查询时统计,无需全量拉取。
-- 按字符数分桶(假设 text_column 是你要统计的字段)
SELECT
CASE
WHEN CHAR_LENGTH(text_column) <= 100 THEN '短文本 (0-100字)'
WHEN CHAR_LENGTH(text_column) <= 500 THEN '中文本 (101-500字)'
ELSE '长文本 (500+字)'
END AS text_category,
COUNT(*) AS cnt
FROM your_table
GROUP BY text_category;
PHP 组合处理
如果分类逻辑复杂(例如需要分多个阈值),可以在 PHP 中先查询,再通过数组聚合。
$tweets = DB::table('posts')->select('content')->get();
$buckets = [
'short' => 0, // < 200 字符
'medium' => 0, // 200-1000 字符
'long' => 0 // > 1000 字符
];
foreach ($tweets as $post) {
$len = mb_strlen($post->content);
if ($len < 200) {
$buckets['short']++;
} elseif ($len < 1000) {
$buckets['medium']++;
} else {
$buckets['long']++;
}
}
生成分布图
结合 ECharts 或 Chart.js 展示环形图,效果直观。
<script>
// 使用 Chart.js 示例
const ctx = document.getElementById('myChart');
new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['短文本', '中文本', '长文本'],
datasets: [{
data: [/* 传入 PHP 输出的数组 */],
backgroundColor: ['#4bc0c0', '#ffcd56', '#ff6384']
}]
}
});
</script>
进阶需求:基于时间维度的动态分布
如果你想看“当前实时” vs “历史”的长短传分布,或者按小时/日期的趋势变化:
- Redis 有序集合:以时间戳为 Score,存
长期或短期的标识。 - 时序数据库:如果量很大,建议用 InfluxDB 打点。
- 可视化:用 Grafana + Prometheus 可以免去大量代码,只需在 PHP 中暴露 metrics。
总结建议
| 你的实际场景 | 推荐方案 | 关键代码点 |
|---|---|---|
| 统计 PHP-FPM 请求响应时间 | 中间件打点 + Redis 计数 | microtime 差值 + Redis incr |
| 统计 Swoole 连接时长 | onConnect / onClose 记录时间戳 |
差值计算 + 分桶 |
| 统计数据库长文本比例 | SQL CASE WHEN 分组或 PHP 数组遍历 |
CHAR_LENGTH 或 mb_strlen |
请根据你的项目实际技术栈(ThinkPHP / Laravel / Swoole)选择对应方案,如果我在某个细节上有所误解,欢迎补充更多背景信息,我可以给出更精确的代码示例。