前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >服务端性能优化之瓶颈分析

服务端性能优化之瓶颈分析

原创
作者头像
若水xii
发布2025-02-22 14:54:07
发布2025-02-22 14:54:07
8410
代码可运行
举报
运行总次数:0
代码可运行

引言

刚开年,公司要扩大业务规模,准备接入新的渠道,预计系统处理的业务量要提升几倍,由此提出了性能优化需求。性能优化的技术,有很多,加缓存、分库分表,接入中间件,代码优化等等,但这些都是术,而性能优化之道,在于指标量化,要知道系统目前的状况,性能瓶颈在哪,才能做到有效的优化,性能优化同样遵循82原则,80%的性能瓶颈,在不到20%的模块中,由此,我开启了系统分析之路。

收集数据

对于后端来讲,对外提供的主要是接口,接口最主要的评估数据,在于响应速度和并发量,我们的系统目前还没有遇到大规模并发的情况,所以主要分析响应速度,于是我在每个系统的服务器入口处,都加了代码用于统计接口时间,大致按controller, method, time的格式,单独写入日志记录下每次请求的响应时间,从业务低谷期到高峰期,收集了差不多一整天的数据。日志格式大概如下:

代码语言:txt
复制
xxController xxMethod 0.052
xxController xxMethod 1.23

定义评估指标

有了每个接口的响应时间,需要对响应数据进行统计,我大概整理了这么几个指标,按接口分类,统计最小请求时间,最大请求时间,请求总数,平均请求时间。请求总数用于分析系统频繁请求的api是哪些,平均请求时间用于反映哪些接口比较慢,影响用户体验,最小最大时间则用于分析接口是否有波动,结合平均时间,看是偶尔慢还是一直都慢

数据统计

有了上述指标,也有了日志,要做统计就很方便了,甚至都不用自己写代码,我把需求描述给chatgpt,自动生成了下列python代码

代码语言:python
代码运行次数:0
复制
import os
from collections import defaultdict
from openpyxl import Workbook

# 日志文件路径
log_file_path = "request_time.log"

# 定义一个存储所有数据的字典,接口名为键,值为每个接口的统计数据
stats = defaultdict(lambda: {"min_time": float("inf"),  # 最小请求时间
                             "max_time": float("-inf"),  # 最大请求时间
                             "total_time": 0,  # 总请求时间
                             "count": 0})  # 请求次数

# 读取文件并统计
if os.path.exists(log_file_path):
    with open(log_file_path, "r") as f:
        for line in f:
            # 去除首尾空白符
            line = line.strip()
            if not line:
                continue  # 跳过空行

            # 假设日志格式为:<类名> <接口函数名> <请求时间>
            parts = line.split()  # 使用空格分割
            if len(parts) != 3:  # 如果一行不是三个部分,跳过
                continue

            class_name, api_name, request_time_str = parts

            try:
                # 转换请求时间为浮点数
                request_time = float(request_time_str)
            except ValueError:
                # 如果请求时间无法转换为浮点数,跳过该行
                continue

            # 生成唯一的接口标识,如 "类名.接口名"
            api_identifier = f"{class_name}.{api_name}"

            # 更新统计信息
            stats[api_identifier]["min_time"] = min(stats[api_identifier]["min_time"], request_time)
            stats[api_identifier]["max_time"] = max(stats[api_identifier]["max_time"], request_time)
            stats[api_identifier]["total_time"] += request_time
            stats[api_identifier]["count"] += 1
else:
    print(f"日志文件 {log_file_path} 不存在!")
    exit(1)

sorted_data = []

for api_identifier, data in stats.items():
    count = data["count"]
    if count > 0:
        avg_time = data["total_time"] / count  # 计算平均时间
    else:
        avg_time = 0
    sorted_data.append({
        "api": api_identifier,
        "min_time": data["min_time"],
        "max_time": data["max_time"],
        "count": count,
        "avg_time": avg_time
    })

# 提供排序选项:按平均时间排序或按次数排序
sort_by = "count"  # 可选:"avg_time" 或 "count"
reverse_order = True  # True 表示从大到小排序,False 表示从小到大排序

if sort_by == "avg_time":
    sorted_data = sorted(sorted_data, key=lambda x: x["avg_time"], reverse=reverse_order)
elif sort_by == "count":
    sorted_data = sorted(sorted_data, key=lambda x: x["count"], reverse=reverse_order)

# 输出排序结果

wb = Workbook()

ws = wb.active
ws.append(['接口', '最短时间', '最长时间', '次数', '平均时间'])

for data in sorted_data:
    ws.append([data['api'], data['min_time'], data['max_time'], data['count'], f"{data['avg_time']:.3f}"])

wb.save('request_time.xlsx')

因为包含多个服务,我则把多个服务的日志分别处理,最后汇总excel就搞定了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 收集数据
  • 定义评估指标
  • 数据统计
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档