mingyuanyun / ggcp-http
基于 GuzzleHttp 封装的 HTTP 请求服务,可通过服务配置开启调链追踪分析、监控预警
v1.3.4
2021-11-01 07:22 UTC
Requires
- php: >=5.6
- guzzlehttp/guzzle: ^6.5
- mongodb/mongodb: ^1.6
This package is auto-updated.
Last update: 2024-10-29 06:06:07 UTC
README
云链公共产品组提供的跨应用调用链追踪扩展支持,底层基于 GuzzleHttp 扩展进行的相关接口调用封装,可以自动识别打通与 iLog 的数据关联
支持
- 自动寻找并利用 iLog 建立不同系统服务间调用的关联,无需业务手动设置每次服务调用的调用链数据
- 支持多线程并发调用。遇到多个乱序服务调用的情况,可以有效提升服务调用的性能
- 自动采集服务调用过程中的请求、响应以及网络传输过程的各种指标数据
性能测试
先放一份简单的性能分析对比,每种请求的测试场景均为发起 100 个请求,其中 CURL 的原生调用采用日常开发中常见的逻辑简单封装实现:
调用方式 | GgcpHttp 总耗时 | CURL 总耗时 | GgcpHttp 平均单个接口耗时 | CURL 平均单个接口耗时 |
---|---|---|---|---|
同步发起 100 个 Get 请求 | 2880.729ms | 10729.794ms | 28.807ms | 107.297ms |
同步发起 100 个 Post 请求 | 19008.264ms | 33206.679ms | 190.082ms | 332.066ms |
异步发起 100 个 Get 请求 | 1341.636ms | - | 13.416ms | - |
异步发起 100 个 Post 请求 | 1557.712ms | - | 15.577ms | - |
配置 && 使用
准备数据采集器
服务调用所需采集的数据,需要通过采集器统一采集到指定的存储空间中,如未提供采集器配置,且通过默认配置无法初始化采集器的话,将无法正常采集所需的数据。目前仅支持数据统一采集存储到 MongoDB
# 在合适的位置做好采集器的初始化工作
$config = [
'engine' => 'mongo',
'options' => [
'host' => 'mongodb://127.0.0.1:27017',
'username' => 'root', // 默认无账号密码
'password' => '123',
],
];
\GgcpHttp\Client::initCollection($config);
你也可以在需要发起服务调用的时候再提供采集器配置
$config = [
'engine' => 'mongo',
'options' => [
'host' => 'mongodb://127.0.0.1:27017',
'username' => 'root', // 默认无账号密码
'password' => '123',
],
];
\GgcpHttp\Client::prepare(['collection' => $config])->getSender()->get('https://www.domain.com/api/get');
发起请求
$sender = \GgcpHttp\Client::prepare()->getSender();
$bodyData = ['id' => 1, 'type' => 2];
// 发起 GET 请求
$response = $sender->get('https://www.domain.com/api/get');
// 发起 POST 请求
$response = $sender->post('https://www.domain.com/api/post', $bodyData);
// 发起 POST 请求,传输 JSON 格式的数据
$response = $sender->postWithJson('https://www.domain.com/api/post', $bodyData);
// 发起 POST 请求,传输 FORM 格式的数据
$response = $sender->postWithForm('https://www.domain.com/api/post', $bodyData);
if (!$response->isSuccess(true)) {
// 接口请求失败的处理
} else {
$resData = $response->isJson() ? $response->toArray() : $response->toString();
}
异步发起单个请求
$sender = \GgcpHttp\Client::prepare()->getSender();
$sender->getAsync('https://www.domain.com/api/get', [], ['success' => function (\GgcpHttp\Response $response) {
$resData = $response->toArray();
# todo something
}]);
异步发起多个请求
$sender = \GgcpHttp\Client::prepare()->getSender();
$options = [
'success' => function (\GgcpHttp\Response $response) {
$resData = $response->toArray();
# todo something
return true;
}
];
$promises = [
// 该接口注册成功回调函数
'api1' => $sender->getAsync('https://www.domain.com/api/get', [], $options),
// 该接口不注册成功回调函数
'api2' => $sender->getAsync('https://www.domain.com/api/get'),
];
// 两个接口均请求完成后才返回结果
$results = GuzzleHttp\Promise\Utils\unwrap($promises);
$ok = $results['api1']; // return true
$response = $results['api2'];
if (!$response->isSuccess(true)) {
// 接口请求失败的处理
} else {
$resData = $response->isJson() ? $response->toArray() : $response->toString();
}
发起请求时对 Header 的处理
为了能够让每一个发起的请求,都能在某个调用链上找到。我们会往即将发起的请求的 Request Header 中加入总共三个请求头参数:X-Trace-Id, X-Span-Id, X-Sub-Span-Id
- X-Trace-Id: 一条完整的调用链中,唯一的 ID 标识。如果从调用方的 Request Header 中能找到 X-Trace-Id 的数据,则接下来发起的所有子请求中,都会带上相同值的 TraceId
- X-Span-Id: 调用方自己的 SpanId,用于告诉子请求是哪一个父请求发起的调用
- X-Sub-Span-Id: 调用方分配给子请求的 SpanId,主要用于调用方自身做采集数据收集时的数据整理。调用方可根据自己的情况选择是否作为自己唯一的 SpanId,正常情况下内部业务接口以 iLog 产生的 subLogId 作为自身唯一的 SpanId
数据采集器说明
数据采集器主要采集以下的信息:
- 请求开始/结束时间
- 请求处理过程中每个环节的耗时(域名解析耗时、TCP Connect 耗时等)
- 请求的 Request、Response 信息
- 请求失败时的异常信息
一个完整的采集信息格式如下:
{
"traceId": "ilog_60307f6be15f1",
"spanId": "ilog_60307f6bf1ac1",
"parentId": "ilog_60307f6bf1ea0",
"parentLogId": "ilog_60307f6bf1ea0",
"parentUrl": "https://www.domain1.com/v2/api",
"requestUrl": "https://www.domain2.com/v1/api",
"responseLogId": "ilog_60307f6bf1ac1",
"duration": {
"startTime": "2021-02-20 11:18:03.966709",
"endTime": "2021-02-20 11:18:04.130406"
},
"transferStat": {
"totalTime": 0.149956,
"namelookupTime": 0.004178,
"connectTime": 0.00784,
"sslVerifyTime": 0.00791,
"waitTime": 0.149081,
"uploadSize": 295,
"uploadSpeed": 1979,
"downloadSize": 56,
"downloadSpeed": 375
},
"requestStat": {
"url": "https://www.domain2.com/v1/api",
"query": "",
"fullUrl": "https://www.domain2.com/v1/api?accessToken=123",
"method": "POST",
"body": "请求体数据",
"header": {
"Content-Length": "295",
"X-Trace-Id": "ilog_60307f6be15f1",
"X-Parent-Log-Id": "ilog_60307f6be162e",
"User-Agent": "GuzzleHttp/6.5.3 curl/7.66.0 PHP/7.1.33",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "www.domain.com",
"X-Span-Id": "ggcphttp_60307f6bec018"
},
"protocVersion": "1.1"
},
"responseStat": {
"statusCode": 200,
"header": {
"Server": "openresty/1.17.8.2",
"Date": "Sat, 20 Feb 2021 03:18:04 GMT",
"Content-Type": "application/json; charset=UTF-8",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Vary": "Accept-Encoding",
"X-Powered-By": "PHP/7.0.8",
"X-Aop": "",
"X-Log-Id": "ilog_60307f6bf1ea0"
},
"content": "{\"code\":0,\"data\":\"\"}"
}
}
调用链追踪
具体的接入使用说明,可联系 huangyj01@mingyuan.com 咨询获取