16、Hyperf 3 微服务系列 - Hyperf 3 使用 Zipkin 分布式调用链追踪
hi,我是温新,一名 PHPer
Hyperf 3 微服务代码已上传至 Github:https://github.com/ziruchu/hyperf3-microservice-code
了解分布式调用链之前,先来看一个问题,如下:
我们在某视频购买了会员,但是并没有升级为 VIP 用户,还是普通用户。由于拆分了很多服务,不知道是哪一个服务出现了问题,此时该如何去定位问题?
hyperf 官方提供了一款非常好用的分布式调用链追踪组件—— hyperf/tracer。该组件可以对和各个跨网络请求进行追踪分析,包括请求方法、异常、Guzzle HTTP 调用、Redis 调用、DB 调用都可以进行监听,还能通过可视化界面进行监控管理。
安装 Zipkin
我这里是在 192.168.31.90 这台服务器进行安装的 zipkin。
使用 docker 进行安装
# 安装
docker pull openzipkin/zipkin
# 启动
docker run --name zipkin -d -p 9411:9411 openzipkin/zipkin
安装完成后,可以通过 http://192.168.31.90:9411/
进行访问,如下图:
Hyperf 调用链追踪
说明:
1、仍旧使用 Nacos 作为注册中心;
2、使用 192.168.31.90 服务器的 shop_consumer_user_9502 项目作为消费者;
3、使用 192.168.31.92 服务器的 shop_provider_user_9605 项目作为服务提供者。
配置服务提供者
当前位置:192.168.31.92 中的 shop_provider_user_9605
第一步:安装组件
# 安装调用链追踪组件
composer require hyperf/tracer
# 可选
# hyperf/tracer 组件默认安装了 Zipkin 相关依赖
# 若要看 redis 效果,可以安装该组件
composer require hyperf/cache
第二步:生成 hyperf/tracer 配置文件
1、生成配置文件
php bin/hyperf.php vendor:publish hyperf/tracer
2、修改配置文件
<?php
// config/autoload/opentracing.php
declare(strict_types=1);
use Zipkin\Samplers\BinarySampler;
return [
// 默认为 zipkin,且没有开启服务
'default' => env('TRACER_DRIVER', 'zipkin'),
'enable' => [
'guzzle' => env('TRACER_ENABLE_GUZZLE', false),
'redis' => env('TRACER_ENABLE_REDIS', false),
'db' => env('TRACER_ENABLE_DB', false),
'method' => env('TRACER_ENABLE_METHOD', false),
'exception' => env('TRACER_ENABLE_EXCEPTION', false),
],
'tracer' => [
'zipkin' => [
'driver' => Hyperf\Tracer\Adapter\ZipkinTracerFactory::class,
'app' => [
'name' => env('APP_NAME', 'skeleton'),
// 本地服务器 IP
'ipv4' => '192.168.31.92',
'ipv6' => null,
'port' => 9602,
],
'options' => [
// 注意:这里是 Zipkin 服务所在的服务器 IP
'endpoint_url' => env('ZIPKIN_ENDPOINT_URL', 'http://192.168.31.90:9411/api/v2/spans'),
'timeout' => env('ZIPKIN_TIMEOUT', 1),
],
'sampler' => BinarySampler::createAsAlwaysSample(),
],
],
// 省略了没有写出来的配置
];
3、配置 .env 文件,开启 Zipkin 服务
APP_NAME=note_provider_user_9605
TRACER_ENABLE_GUZZLE=true
TRACER_ENABLE_REDIS=true
TRACER_ENABLE_DB=true
TRACER_ENABLE_METHOD=true
TRACER_ENABLE_EXCEPTION=true
第三步:配置中间件
配置完驱动之后,采集信息还需要配置一下中间件才能启用采集功能。
<?php
// config/autoload/middlewares.php
return [
'jsonrpc-http' => [
\Hyperf\Tracer\Middleware\TraceMiddleware::class,
],
];
第四步:编写业务代码
1、添加接口方法
<?php
// app/JsonRpc/Interface/UserServiceInterface.php
public function getUserInfoFromCache(int $id);
2、实现接口方法
<?php
// app/JsonRpc/Service/UserService.php
public function getUserInfoFromCache(int $id)
{
$user = User::query()->find($id);
if (empty($user)) {
throw new \RuntimeException('没有该用户');
}
return ResponseTool::success($user->toArray());
}
配置服务消费者
当前位置:192.168.31.90 中的 shop_consumer_user_9502
第一步:安装组件
composer require hyperf/tracer
第二步:生成配置文件
1、生成配置文件
php bin/hyperf.php vendor:publish hyperf/tracer
2、修改配置文件
<?php
// config/autoload/opentracing.php
declare(strict_types=1);
use Zipkin\Samplers\BinarySampler;
return [
'default' => env('TRACER_DRIVER', 'zipkin'),
'enable' => [
'guzzle' => env('TRACER_ENABLE_GUZZLE', false),
'redis' => env('TRACER_ENABLE_REDIS', false),
'db' => env('TRACER_ENABLE_DB', false),
'method' => env('TRACER_ENABLE_METHOD', false),
'exception' => env('TRACER_ENABLE_EXCEPTION', false),
],
'tracer' => [
'zipkin' => [
'driver' => Hyperf\Tracer\Adapter\ZipkinTracerFactory::class,
'app' => [
'name' => env('APP_NAME', 'skeleton'),
'ipv4' => '192.168.31.90',
'ipv6' => null,
'port' => 9502,
],
'options' => [
'endpoint_url' => env('ZIPKIN_ENDPOINT_URL', 'http://192.168.31.90:9411/api/v2/spans'),
'timeout' => env('ZIPKIN_TIMEOUT', 1),
],
'sampler' => BinarySampler::createAsAlwaysSample(),
],
],
];
3、配置 .env 文件,开启 Zipkin 服务
APP_NAME=note_consumer_user_9502
TRACER_ENABLE_GUZZLE=true
TRACER_ENABLE_REDIS=true
TRACER_ENABLE_DB=true
TRACER_ENABLE_METHOD=true
TRACER_ENABLE_EXCEPTION=true
第三步:配置 JsonRPC 追踪开关
JsonRPC 的链路追踪并不在统一配置当中,暂时还属于 Beta
版本的功能。
我们只需要配置 aspects.php
,加入以下 Aspect
即可开启。
提示:不要忘了在对端,添加对应的 TraceMiddleware
<?php
// config/autoload/aspects.php
return [
Hyperf\Tracer\Aspect\JsonRpcAspect::class,
];
第四步:配置中间件
<?php
// config/autoload/middlewares.php
return [
'http' => [
\Hyperf\Tracer\Middleware\TraceMiddleware::class,
],
];
第五步:编写业务代码
1、添加接口方法
<?php
// app\JsonRpc\Interface\UserServiceInterface.php
public function getUserInfoFromCache(int $id);
2、实现接口方法
<?php
// app\JsonRpc\Service\UserService.php
public function getUserInfoFromCache(int $id)
{
return $this->__request(__FUNCTION__, compact('id'));
}
3、编写控制器代码
<?php
// app\Controller\UserController.php
#[GetMapping('/users/getUserInfoFromCache')]
public function getUserInfoFromCache()
{
$id = (int) $this->request->input('id');
$result = $this->userService->getUserInfoFromCache($id);
if ($result['code'] != ResponseCode::SUCCESS) {
throw new \RuntimeException($result['message']);
}
return ResponseTool::success($result['data']);
}
最后启动服务者和消费者。
测试
测试一:使用 postman 或浏览器测试
$ curl http://192.168.31.90:9502/users/getUserInfoFromCache?id=1
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"name": "李四",
"gender": 1,
"created_at": "2023-03-21 04:37:43",
"updated_at": "2023-03-21 04:37:43"
}
}
1、现在打开 Zipkin 后台,然后点 +
号,选择 note_consumer_user_9502
,然后点击 run query
,就能看到查询结果了。
2、点击 SHOW
查看详情
从详情中可以看到 jsonrpc、request、db 等操作。
测试二:服务器出错
现在我们查询一条不存在的记录,然后看看链追踪中是什么情况。
$ curl http://192.168.31.90:9502/users/getUserInfoFromCache?id=111
{
"code": -32000,
"message": "node_provider_user_9605-0.0.0.0:9605-没有该用户"
}
1、我们来看看 Zipkin 中的情况:
2、查看详情
从结果中可以发现,对于出错的请求,调用链会被标记上红色符号,点击该请求就可以进入到详情界面查看具体情况。
还可以查看 SQL 语句,点击一下 db:query 就可以了,这里不截图了。
本篇文章到此结束,我是温新。