接口性能分析扩展

Laravel框架
373
0
0
2022-11-10

项目说明

该扩展致力于分析接口上的优化能力

项目地址: github.com/GodForHeart/laravel-opt...

安装插件:composer require godforheart/laravel-optimizer

生成配置:php artisan optimizer:publish

1. 插件背景

平时项目开发中,经常会遇到n+1查询,接口中执行的sql过多,导致接口性能不加,但是已有接口过多,或开发过程不注意,还能使用数据库日志,来筛选出性能较差,sql调用次数过多的旧接口,便在实际开发中,开发一个符合个人需求的插件,并且个人感觉还挺好用,遂推荐一波

2. 功能介绍

  • 动态开关功能
  • 日志存储类型:本地日志,数据库,日志分析平台(暂不可使用)
  • 安全日志模式:安全模式下不会记录请求参数和响应内容,以及只记录MD5(sql)
  • 持久化方式:同步,异步(异步处理日志,降低插件对接口响应时间的影响度)
  • 忽略指定接口日志
  • 额外请求参数日志:如需要记录请求用户id(每个项目授权方式不同,插件不集成改功能,需使用者自行配置)
  • 忽略指定请求参数:如不希望password记录,可忽略该参数
  • 可开启单条数据库sql日志(默认开启)
  • 可开启单条redis操作日志(默认关闭,开启该功能需要额外配置,下文会介绍)
  • 日志限制器:三种策略(独立请求,根据ip规则,根据接口uri规则)
  • 日志限制器:两种规则(随机,顺序)
  • 日志限制器:日志比例(百分比,0-100,当为0时,等同于关闭,当为100时,等同于无限制)

3. 配置信息

配置文件地址:config/optimizer.php

<?php
return [
    //  是否开启扩展 
    'enable' => (bool)env('OPTIMIZER_ENABLE', true),

    //  是否开启平台日志(可 本地日志+平台日志 双线) 
    'enable_platform_log' => (bool)env('OPTIMIZER_ENABLE_PLATFORM_LOG', false),

    /**
     * 默认日志存储类型,默认日志文件,可选:
     *          logger:本地日志
     *          database:数据库
     *          platform:日志分析平台
     */ 
    'default' => env('OPTIMIZER_DEFAULT', 'logger'),

    //  是否安全模式,安全模式下,不会记录请求参数和响应内容,以及只记录MD5(sql) 
    'safe_mode' => (bool)env('OPTIMIZER_SAFE_MODE', false),
    .
    .
    .
    'limiter' => [
        /**
         * strategy(日志策略):
         *          request:独立请求
         *          ip:根据独立ip
         *          uri:根据相同uri
         */ 
        'strategy' => env('OPTIMIZER_LIMITER_STRATEGY', 'request'),

        /**
         * rule(日志规则):
         *          orderly:有序的
         *          disorderly:无序的,伪随机(请注意,大方向上会超过设定的占比)
         */ 
        'rule' => env('OPTIMIZER_LIMITER_RULE', 'orderly'),

        /**
         * rate(占比):一百次中记录多少次,1-100
         */ 
        'rate' => (int)env('OPTIMIZER_LIMITER_RATE', 100),
    ]
];

4. 中间件使用方式

在需要的位置增加改扩展中间件,如个人需要在【api】中间件组中增加

<?php
.
.
.
class Kernel extends HttpKernel
{
    .
    .
    .
    protected $middlewareGroups = [
        .
        .
        .

        'api' => [
            .
            .
            .
            \Godforheart\LaravelOptimizer\Middleware\OptimizerLog::class
        ],
    ];
}

5. Redis日志配置

在config/app.php文件中,providers数组中,把:

Illuminate\Redis\RedisServiceProvider::class

替换成

\Godforheart\LaravelOptimizer\OptimizerRedisServiceProvider::class

既可监听【Redis门面】和【Cache门店(使用redis)】的操作日志

6. 日志示例

该次请求,经过测试,使用异步日志方式,约占用接口【0.5 - 1】ms 的执行时间影响度较小,请根据实际情况,进行选择使用

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 2.84ms; select * from `personal_access_tokens` where `personal_access_tokens`.`id` = "18" limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 1.03ms; select * from `users` where `users`.`id` = 1 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 2.83ms; update `personal_access_tokens` set `last_used_at` = "2022-07-21 16:09:26", `personal_access_tokens`.`updated_at` = "2022-07-21 16:09:26" where `id` = 18

[2022-07-21 16:09:26] local.INFO: optimizer:singleRedis:[connection:default] execution times: 0.18ms; get "aa"

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 1.03ms; select count(*) as aggregate from `organizations`

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.64ms; select * from `organizations` limit 10 offset 0

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.68ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.95ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.66ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.57ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.7ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.61ms; select * from `dic_areas` where `dic_areas`.`id` = 0 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.64ms; select * from `dic_areas` where `dic_areas`.`id` = 330000 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.63ms; select * from `dic_areas` where `dic_areas`.`id` = 330100 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer:singleSql:[connection:mysql] execution times: 0.64ms; select * from `dic_areas` where `dic_areas`.`id` = 330104 limit 1

[2022-07-21 16:09:26] local.INFO: optimizer {"request_id":"2c6ce952-843a-47be-943b-d79c38350615","api_uri":"organizations","request_method":"GET","time":0.07205510139465332,"business_time":0.0471041202545166,"request_params":[],"response_content":"{\"status\":\"success\",\"result\":[{\"id\":1,\"platform_id\":\"11111111111\",\"name\":\"性能分析平台450752189154113\",\"alias_name\":\"性能分析2\",\"contact_name\":\"哈哈哈\",\"contact_phone\":\"150********\",\"contact_email\":\"610100380@qq.com\",\"memo\":\"测试\",\"status_name\":\"正常\",\"province_name\":null,\"city_name\":null,\"district_name\":null,\"created_at\":\"2021-10-21 17:13:51\",\"updated_at\":\"2022-07-21 09:42:20\"},{\"id\":2,\"platform_id\":\"22222222222222222222\",\"name\":\"科技有限公司\",\"alias_name\":\"亿云互动\",\"contact_name\":\"吴**\",\"contact_phone\":\"186********\",\"contact_email\":\"\",\"memo\":\"测试\",\"status_name\":\"正常\",\"province_name\":null,\"city_name\":null,\"district_name\":null,\"created_at\":\"2021-10-27 16:25:00\",\"updated_at\":\"2021-10-27 16:25:02\"},{\"id\":6,\"platform_id\":\"3333333333333333333\",\"name\":\"营销策划有限公司\",\"alias_name\":\"聚力\",\"contact_name\":\"呵呵呵\",\"contact_phone\":\"150********\",\"contact_email\":\"610100380@qq.com\",\"memo\":\"备注\",\"status_name\":\"正常\",\"province_name\":\"浙江省\",\"city_name\":\"杭州市\",\"district_name\":null,\"created_at\":\"2022-02-10 14:36:12\",\"updated_at\":\"2022-02-10 14:36:12\"}],\"meta\":{\"current_page\":1,\"last_page\":1,\"per_page\":10,\"total\":3}}","logs":[{"sql":"select * from `personal_access_tokens` where `personal_access_tokens`.`id` = ? limit 1","bindings":["18"],"time":0.0028399999999999996,"connection":"mysql"},{"sql":"select * from `users` where `users`.`id` = ? limit 1","bindings":[1],"time":0.00103,"connection":"mysql"},{"sql":"update `personal_access_tokens` set `last_used_at` = ?, `personal_access_tokens`.`updated_at` = ? where `id` = ?","bindings":["2022-07-21 16:09:26","2022-07-21 16:09:26",18],"time":0.00283,"connection":"mysql"},{"sql":"select count(*) as aggregate from `organizations`","bindings":[],"time":0.00103,"connection":"mysql"},{"sql":"select * from `organizations` limit 10 offset 0","bindings":[],"time":0.00064,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.00068,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.00095,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.00066,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.00057,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.0007,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[0],"time":0.00061,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[330000],"time":0.00064,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[330100],"time":0.00063,"connection":"mysql"},{"sql":"select * from `dic_areas` where `dic_areas`.`id` = ? limit 1","bindings":[330104],"time":0.00064,"connection":"mysql"}],"redis_logs":[{"time":"0.00018","command":"get","parameters":["aa"],"connection_name":"default"}]}

7. 配置推荐

1、全量请求日志(日志量大,生产环境请勿使用)

  • 占比(limiter.rate):100

2、所有接口共用日志记录频率(每10次请求,记录一次日志,缺点是部分请求量少的接口,可能正好请求在不记录中,导致接口无日志)

  • 日志策略(limiter.strategy):request
  • 顺序规则(limiter.rule):orderly
  • 请求占比(limiter.rate):10

3、不同接口地址独立规则(推荐该方式),不同接口独立计算,顺序请求记录,每10次记录一次日志

  • 日志策略(limiter.strategy):uri
  • 顺序规则(limiter.rule):orderly
  • 请求占比(limiter.rate):10