# 服务监控 微服务治理的一个核心需求便是服务可观察性。作为微服务的牧羊人,要做到时刻掌握各项服务的健康状态,并非易事。云原生时代这一领域内涌现出了诸多解决方案。本组件对可观察性当中的重要支柱遥测与监控进行了抽象,方便使用者与既有基础设施快速结合,同时避免供应商锁定。 ## 安装 ### 通过 Composer 安装组件 ```bash composer require hyperf/metric ``` [hyperf/metric](https://github.com/hyperf/metric) 组件默认安装了 [Prometheus](https://prometheus.io/) 相关依赖。如果要使用 [StatsD](https://github.com/statsd/statsd) 或 [InfluxDB](http://influxdb.com),还需要执行下面的命令安装对应的依赖: ```bash # StatsD 所需依赖 composer require domnikl/statsd # InfluxDB 所需依赖 composer require influxdb/influxdb-php ``` ### 增加组件配置 如文件不存在,可执行下面的命令增加 `config/autoload/metric.php` 配置文件: ```bash php bin/hyperf.php vendor:publish hyperf/metric ``` ## 使用 ### 配置 #### 选项 * `default`:配置文件内的 `default` 对应的值则为使用的驱动名称。驱动的具体配置在 `metric` 项下定义,使用与 `key` 相同的驱动。 ```php 'default' => env('TELEMETRY_DRIVER', 'prometheus'), ``` * `use_standalone_process`: 是否使用 `独立监控进程`。推荐开启。关闭后将在 `Worker进程` 中处理指标收集与上报。 ```php 'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true), ``` * `enable_default_metric`: 是否统计默认指标。默认指标包括内存占用、系统 CPU 负载以及Swoole Server 指标和 Swoole Coroutine 指标。 ```php 'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true), ``` * `default_metric_inteval`: 默认指标推送周期,单位为秒,下同。 ```php 'default_metric_inteval' => env('DEFAULT_METRIC_INTEVAL', 5), ``` #### 配置 Prometheus 使用 Prometheus 时,在配置文件中的 `metric` 项增加 Prometheus 的具体配置。 ```php use Hyperf\Metric\Adapter\Prometheus\Constants; return [ 'default' => env('TELEMETRY_DRIVER', 'prometheus'), 'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true), 'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true), 'default_metric_inteval' => env('DEFAULT_METRIC_INTEVAL', 5), 'metric' => [ 'prometheus' => [ 'driver' => Hyperf\Metric\Adapter\Prometheus\MetricFactory::class, 'mode' => Constants::SCRAPE_MODE, 'namespace' => env('APP_NAME', 'skeleton'), 'scrape_host' => env('PROMETHEUS_SCRAPE_HOST', '0.0.0.0'), 'scrape_port' => env('PROMETHEUS_SCRAPE_PORT', '9502'), 'scrape_path' => env('PROMETHEUS_SCRAPE_PATH', '/metrics'), 'push_host' => env('PROMETHEUS_PUSH_HOST', '0.0.0.0'), 'push_port' => env('PROMETHEUS_PUSH_PORT', '9091'), 'push_inteval' => env('PROMETHEUS_PUSH_INTEVAL', 5), ], ], ]; ``` Prometheus 有两种工作模式,爬模式与推模式(通过 Prometheus Pushgateway ),本组件均可支持。 使用爬模式(Prometheus 官方推荐)时需设置: ```php 'mode' => Constants::SCRAPE_MODE ``` 并配置爬取地址 `scrape_host`、爬取端口 `scrape_port`、爬取路径 `scrape_path`。Prometheus 可以在对应配置下以HTTP访问形式拉取全部指标。 > 注意:爬模式下,必须启用独立进程,即 use_standalone_process = true。 使用推模式时需设置: ```php 'mode' => Constants::PUSH_MODE ``` 并配置推送地址 `push_host`、推送端口 `push_port`、推送间隔 `push_inteval`。只建议离线任务使用推模式。 #### 配置 StatsD 使用 StatsD 时,在配置文件中的 `metric` 项增加 StatsD 的具体配置。 ```php return [ 'default' => env('TELEMETRY_DRIVER', 'statd'), 'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true), 'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true), 'metric' => [ 'statsd' => [ 'driver' => Hyperf\Metric\Adapter\StatsD\MetricFactory::class, 'namespace' => env('APP_NAME', 'skeleton'), 'udp_host' => env('STATSD_UDP_HOST', '127.0.0.1'), 'udp_port' => env('STATSD_UDP_PORT', '8125'), 'enable_batch' => env('STATSD_ENABLE_BATCH', true), 'push_inteval' => env('STATSD_PUSH_INTEVAL', 5), 'sample_rate' => env('STATSD_SAMPLE_RATE', 1.0), ], ], ]; ``` StatsD 目前只支持 UDP 模式,需要配置 UDP 地址 `udp_host`,UDP 端口 `udp_port`、是否批量推送 `enable_batch`(减少请求次数)、批量推送间隔 `push_inteval` 以及采样率`sample_rate`。 #### 配置 InfluxDB 使用 InfluxDB 时,在配置文件中的 `metric` 项增加 InfluxDB 的具体配置。 ```php return [ 'default' => env('TELEMETRY_DRIVER', 'influxdb'), 'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true), 'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true), 'metric' => [ 'influxdb' => [ 'driver' => Hyperf\Metric\Adapter\InfluxDB\MetricFactory::class, 'namespace' => env('APP_NAME', 'skeleton'), 'host' => env('INFLUXDB_HOST', '127.0.0.1'), 'port' => env('INFLUXDB_PORT', '8086'), 'username' => env('INFLUXDB_USERNAME', ''), 'password' => env('INFLUXDB_PASSWORD', ''), 'dbname' => env('INFLUXDB_DBNAME', true), 'push_inteval' => env('INFLUXDB_PUSH_INTEVAL', 5), ], ], ]; ``` InfluxDB 使用默认的 HTTP 模式,需要配置地址 `host`,UDP端口 `port`、用户名 `username`、密码 `password`、`dbname` 数据表以及批量推送间隔 `push_inteval`。 ### 基本抽象 遥测组件对常用的三种数据类型进行了抽象,以确保解耦具体实现。 三种类型分别为: * 计数器(Counter): 用于描述单向递增的某种指标。如 HTTP 请求计数。 ```php interface CounterInterface { public function with(string ...$labelValues): self; public function add(int $delta); } ``` * 测量器(Gauge):用于描述某种随时间发生增减变化的指标。如连接池内的可用连接数。 ```php interface GaugeInterface { public function with(string ...$labelValues): self; public function set(float $value); public function add(float $delta); } ``` * 直方图(Histogram):用于描述对某一事件的持续观测后产生的统计学分布,通常表示为百分位数或分桶。如HTTP请求延迟。 ```php interface HistogramInterface { public function with(string ...$labelValues): self; public function put(float $sample); } ``` ### 配置中间件 配置完驱动之后,只需配置一下中间件就能启用请求 Histogram 统计功能。 打开 `config/autoload/middlewares.php` 文件,示例为在 `http` Server 中启用中间件。 ```php [ \Hyperf\Metric\Middleware\MetricMiddeware::class, ], ]; ``` ### 自定义使用 通过HTTP中间件遥测仅仅是本组件用途的冰山一角,您可以注入 `Hyperf\Metric\Contract\MetricFactoryInterface` 类来自行遥测业务数据。比如:创建的订单数量、广告的点击数量等。 ```php metricFactory->makeCounter('order_created', ['order_type']); $counter->with($order->type)->add(1); // 订单逻辑... } } ``` `MetricFactoryInterface` 中包含如下工厂方法来生成对应的三种基本统计类型。 ```php public function makeCounter($name, $labelNames): CounterInterface; public function makeGauge($name, $labelNames): GaugeInterface; public function makeHistogram($name, $labelNames): HistogramInterface; ``` 上述例子是统计请求范围内的产生的指标。有时候我们需要统计的指标是面向完整生命周期的,比如统计异步队列长度或库存商品数量。此种场景下可以监听 `MetricFactoryReady` 事件。 ```php container = $container; } public function listen(): array { return [ MetricFactoryReady::class, ]; } public function process(object $event) { $redis = $this->container->get(Redis::class); $gauge = $event ->factory ->makeGauge('queue_length', ['driver']) ->with('redis'); while (true) { $length = $redis->llen('queue'); $gauge->set($length); sleep(1); } } } ``` > 工程上讲,直接从 Redis 查询队列长度不太合适,应该通过队列驱动 `DriverInterface` 接口下的 `info()` 方法来获取队列长度。这里只做简易演示。您可以在本组件源码的`src/Listener` 文件夹下找到完整例子。 ### 注解 您可以使用 `@Counter(name="stat_name_here")` 和 `@Histogram(name="stat_name_here")` 来统计切面的调用次数和运行时间。 关于注解的使用请参阅[注解章节](https://doc.hyperf.io/#/zh/annotation)。