EasySwoole之链路追踪

2020-06-30 10:29:39 浏览数 (1)

什么是链路追踪

  • 链路追踪一般常用于分布式架构中,当实现一个功能的同时,可能会依次调用多个接口,那么此时这一些列的接口调用,称为调用链。想要实现调用链,那么就需要对每次调用的链接进行标识也就是pointId,方便出现调用问题的时候排查问题,但是有调用并不是同级,所以还需要用parentId来标识上下级关系。具体请查看链接 一文读懂链路追踪

EasySwoole中实现Api链路追踪

  • 安装组件 composer require easyswoole/tracker
  • onRequest事件(请求开始)
代码语言:javascript复制
public static function onRequest(Request $request, Response $response): bool
    {
        //链路追踪
        $point = PointContext::getInstance()->createStart('onRequest');
        $point->setStartArg([
            'uri' => $request->getUri()->__toString(),//获取请求的url
            'get' => $request->getQueryParams(),//get参数(注意:若POST与GET存在同键名参数,则以GET为准)
            'post'=> $request->getRequestParam()//post参数
        ]);
        return true;
    }
  • 创建数据库
代码语言:javascript复制
CREATE TABLE `api_tracker_point_list` (
  `point_id` varchar(50) NOT NULL,
  `parent_id` varchar(50) DEFAULT NULL,
  `point_name` varchar(255) DEFAULT NULL COMMENT '请求名称',
  `is_next` int(11) NOT NULL DEFAULT '0',
  `depth` int(11) NOT NULL DEFAULT '0',
  `status` varchar(10) NOT NULL DEFAULT '' COMMENT '状态',
  `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '请求ip',
  `url` varchar(1000) NOT NULL DEFAULT '' COMMENT '请求地址',
  `result` text COMMENT '请求结果',
  `data` text COMMENT '请求参数',
  `add_time` varchar(15) NOT NULL DEFAULT '0' COMMENT '访问时间',
  `start_time` varchar(15) NOT NULL DEFAULT '0' COMMENT '请求开始时间',
  `end_time` varchar(15) NOT NULL DEFAULT '0' COMMENT '请求结束时间',
  `spend_time` decimal(15,3) DEFAULT '0.000' COMMENT '调用耗时',
  PRIMARY KEY (`point_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • afterRequest事件(请求结束)
代码语言:javascript复制
public static function afterRequest(Request $request, Response $response): void
    {
        //获取当前ip
        $serv = ServerManager::getInstance()->getSwooleServer();
        $client = $serv->getClientInfo($request->getSwooleRequest()->fd);
        $clientAddress = $client['remote_ip'];
        $xri = $request->getHeader('x-real-ip');
        $xff = $request->getHeader('x-forwarded-for');
        if ($clientAddress === '127.0.0.1'){
            if (!empty($xri)) {  // 如果有xri 则判定为前端有NGINX等代理
                $clientAddress = $xri[0];
            } elseif (!empty($xff)) {  // 如果不存在xri 则继续判断xff
                $list = explode(',', $xff[0]);
                if (isset($list[0])) $clientAddress = $list[0];
            }
        }

        $point = PointContext::getInstance()->startPoint();
        $point->end();
        $array = Point::toArray($point);
        $data = [];

        foreach ($array as  $v)
        {
            $data['point_id'] = $v['pointId'];
            $data['point_name'] = $v['pointName'];
            $data['parent_id'] = $v['parentId'];
            $data['depth'] = $v['depth'];
            $data['is_next'] = $v['isNext'] ? 1 : 0;
            $data['start_time'] = $v['startTime'];
            $data['end_time'] = $v['endTime'];
            $data['spend_time'] = $v['endTime']-$v['startTime'];
            $data['status'] = $v['status'];
            $arg = $v['startArg'];
            $data['url'] = explode(':9503',$arg['uri'])[1];
            unset($arg['uri']);
            $data['result'] = $response->getBody()->__toString();
            $data['data'] = json_encode($arg);
            $data['add_time'] = time();
            $data['ip'] = $clientAddress;
			//此处应做个白名单来处理那些api接口调用需要记录到表
            if(strpos(strtolower($data['url']),'api/admin') === false )
            {
                ApiTrackerModel::create($data)->save();

            }


        }
    }
  • 效果图
此时简单的链路追踪已实现,并没有多次调用链接,如果想要实现复杂的链路追踪,请移步easyswoole官网->组件->链路追踪组件查看,其次此组件可以当成甩锅神器(前端接口出现的问题)以及系统性能排查来使用

来自北溟有鱼QAQ https://www.umdzz.cn

0 人点赞