首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >TransferStatistics使用实例:应用和SQL监控系统workerman

TransferStatistics使用实例:应用和SQL监控系统workerman

原创
作者头像
OwenZhang
发布2022-05-30 15:02:31
发布2022-05-30 15:02:31
5780
举报
文章被收录于专栏:Owen's WorldOwen's World

本文环境 CentOS8.0,PHP8.1,Nginx1.8,Workerman 4.0\ 不懂的可以评论 著作权归OwenZhang所有。商业转载请联系OwenZhang获得授权,非商业转载请注明出处。

workerman介绍

Workerman是一款纯PHP开发的开源高性能的PHP 应用容器。

Workerman不是重复造轮子,它不是一个MVC框架,而是一个更底层更通用的服务框架,你可以用它开发tcp代理、梯子代理、做游戏服务器、邮件服务器、ftp服务器、甚至开发一个php版本的redis、php版本的数据库、php版本的nginx、php版本的php-fpm等等。Workerman可以说是PHP领域的一次创新,让开发者彻底摆脱了PHP只能做WEB的束缚。

实际上Workerman类似一个PHP版本的nginx,核心也是多进程+Epoll+非阻塞IO。Workerman每个进程能维持上万并发连接。由于本身常驻内存,不依赖Apache、nginx、php-fpm这些容器,拥有超高的性能。同时支持TCP、UDP、UNIXSOCKET,支持长连接,支持Websocket、HTTP、WSS、HTTPS等通讯协议以及各种自定义协议。拥有定时器、异步socket客户端、异步Redis、异步Http、异步消息队列等众多高性能组件。

TransferStatistics项目

TransferStatistics 使用webman开发的一个应用监控系统,用于查看应用调用记录、请求量、调用耗时、调用分析等。

系统使用UDP接收上报数据;使用Redis存储、汇总数据

由于是使用redis存储,所以我做了个定时删除一周前的数据

定时删除redis db7 statistic key

image.png
image.png
代码语言:txt
复制
#!/bin/bash
redis-cli <<END
select 7
flushdb 
END

tcp/udp传输介绍

TCP/IP模型的运输层有两个不同的协议:UDP用户数据报协议与TCP传输控制协议。

运输层无法保证数据的可靠传输,只能通过应用层来实现了,实现的方式可以参照TCP可靠性传输的方式,只是实现不在传输层,实现转移到了应用层,主要通过实现确认机制、重传机制、窗口确认等机制来实现可靠传输,有RUDP、RTP、UDT等开源程序利用UDP实现了可靠的数据传输,此外有结合TCP的可靠与UDP速度的权衡KCP协议。

由于TCP本身是面向字节流的,无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。

消息定长:发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

设置消息边界:服务端从网络流中按消息边界分离出消息内容,在包尾增加回车换行符进行分割,例如FTP协议。

将消息分为消息头和消息体:消息头中包含表示消息总长度(或者消息体长度)的字段。

项目地址

https://github.com/hsk99/transfer-statistics

所需环境

PHP版本不低于7.3,并安装 Redis 拓展

安装

composer安装

创建项目

composer create-project hsk99/transfer-statistics

下载安装

1、下载 或git clone https://github.com/hsk99/transfer-statistics

2、执行命令composer install

配置

1、config/redis.php 设置 Redis

代码语言:txt
复制
<?php

return [
    'default' => [
        'host'     => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', ''),
        'port'     => env('REDIS_PORT', '6379'),
        'database' => 7,
        'prefix'   => 'statistic:',
    ],
];

2、config/app.php 设置 登录用户名、密码

代码语言:txt
复制
<?php

return [
    'debug'            => true,
    'default_timezone' => 'Asia/Shanghai',
    'admin_name'       => 'root',
    'admin_password'   => 'owenzhang',
];

3、config/server.php 设置 WebServer

代码语言:txt
复制
<?php

return [
    'listen'           => 'http://127.0.0.1:8788',
    'transport'        => 'tcp',
    'context'          => [],
    'name'             => 'server',
    'count'            => 1,
    'user'             => '',
    'group'            => '',
    'pid_file'         => runtime_path() . '/master.pid',
    'stdout_file'      => runtime_path() . '/stdout.log',
    'log_file'         => runtime_path() . '/master.log',
    'max_request'      => 1000000,
    'max_package_size' => 100 * 1024 * 1024,
];

4、config/process.php 设置 采集服务

代码语言:txt
复制
<?php

return [
    // File update detection and automatic reload
    'monitor' => [
        'handler'     => process\FileMonitor::class,
        'reloadable'  => false,
        'constructor' => [
            // Monitor these directories
            'monitor_dir' => [
                app_path(),
                config_path(),
                base_path() . '/process',
                base_path() . '/support',
                base_path() . '/resource',
                base_path() . '/.env',
                base_path() . '/expand',
                base_path() . '/Protocols',
            ],
            // Files with these suffixes will be monitored
            'monitor_extensions' => [
                'php', 'html', 'htm', 'env'
            ]
        ],
        'bootstrap' => []
    ],
    // Statistic
    'statistic' => [
        'handler'   => process\Statistic::class,
        'listen'    => 'statistic://0.0.0.0:55674',
        'count'     => 1,
        'transport' => 'udp',
        'bootstrap' => []
    ],
];

运行

执行命令php start.php start

查看统计

浏览器访问http://ip地址:8788

workerman项目的配置

config/app.php

添加上报地址

代码语言:txt
复制
    'statisticAddress' => 'udp://127.0.0.1:55674', // udp上报地址 一般用于api接口请求

config/middleware.php

添加上报中间件

代码语言:txt
复制
    'admin' => [
        \app\middleware\Statistic::class, // 接口请求即时上报
        \app\middleware\StatisticSQL::class, // SQL监控即时上报
        \app\middleware\ApiRoute::class,
        \app\middleware\ApiBaseRequest::class,
        \app\middleware\ActionHook::class,
    ],

app/middleware/Statistic.php

添加接口请求即时上报类

代码语言:txt
复制
<?php

namespace app\middleware;

use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use app\extend\Client\StatisticClient;

class Statistic implements MiddlewareInterface
{
    public function process(Request $request, callable $next): Response
    {
        $ip         = $request->getRealIp(true);
        $controller = $request->controller;
        $action     = $request->action;
        $transfer   = $controller . '::' . $action;
        $project    = '充电动画项目';
        // 开始计时
        $unique   = StatisticClient::tick($project, $ip, $transfer);
        $response = $next($request);
        $code     = $response->getStatusCode();
        $success  = $code < 400;
        $details  = [
            'ip'              => $request->getRealIp(true) ?? '',                                             // 请求客户端IP
            'url'             => $request->fullUrl() ?? '',                                                             // 请求URL
            'method'          => $request->method() ?? '',                                                              // 请求方法
            'request_param'   => $request->all() ?? [],                                                                 // 请求参数
            'request_header'  => $request->header() ?? [],                                                              // 请求头
            'cookie'          => $request->cookie() ?? [],                                                              // 请求cookie
            'session'         => $request->session()->all() ?? [],                                                      // 请求session
            'response_code'   => $response->getStatusCode() ?? '',                                                      // 响应码
            'response_header' => $response->getHeaders() ?? [],                                                         // 响应头
            'response_body'   => $response->rawBody() ? json_decode($response->rawBody(), true) : [],             // 响应数据(发生异常)
        ];
        // 数据上报
        StatisticClient::report($unique, $project, $ip, $transfer, $success, $code, json_encode($details, JSON_PRESERVE_ZERO_FRACTION | JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE));
        return $response;
    }
}

app/middleware/StatisticSQL.php

开启ThinkORM SQL监听配置

代码语言:txt
复制
// 监听SQL
        'trigger_sql'     => true,

文档网址:

https://static.kancloud.cn/manual/think-orm/1257999

添加SQL监控即时上报类(ThinkORM )

代码语言:txt
复制
<?php

namespace app\middleware;

use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use app\extend\Client\StatisticClient;

class StatisticSQL implements MiddlewareInterface
{
    public function process(Request $request, callable $next): Response
    {
        $response = $next($request);

        // SQL监控
        \think\facade\Db::listen(function ($sql, $runtime, $master) {
		    if ($sql == 'select 1') return true;
			
            $ip      = \request()->getRealIp(true) ?? '';
            $project = '充电动画项目SQL';

            switch (true) {
                case is_numeric($runtime):
                    $transfer = $sql;
                    $cost     = $runtime;
                    break;
                case !is_numeric($runtime) && 'CONNECT' === substr($sql, 0, 7):
                    @preg_match("/UseTime:([0-9]+(\\.[0-9]+)?|[0-9]+(\\.[0-9]+))/", $sql, $result);
                    if (count($result) > 1) {
                        $transfer = substr($sql, strpos($sql, "s ] ") + 4);
                        $cost     = $result[1];
                    } else {
                        $transfer = $sql;;
                        $cost = 0;
                    }
                    break;
                default:
                    $transfer = $sql;;
                    $cost = 0;
                    break;
            }
            StatisticClient::report('', $project, $ip, $transfer, true, 1, json_encode([
                'sql'     => $sql,
                'runtime' => $cost . 's',
                'master'  => $master,
            ], 320), $cost);
        });

        return $response;
    }
}

看效果图

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • workerman介绍
  • TransferStatistics项目
  • tcp/udp传输介绍
    • 项目地址
    • 所需环境
    • 安装
    • composer安装
    • 下载安装
    • 配置
    • 运行
    • 查看统计
  • workerman项目的配置
    • config/app.php
    • config/middleware.php
    • app/middleware/Statistic.php
    • app/middleware/StatisticSQL.php
  • 看效果图
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档