hyperf/doc/zh-tw/metric.md
2020-02-29 13:23:57 +08:00

410 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 服務監控
微服務治理的一個核心需求便是服務可觀察性。作為微服務的牧羊人,要做到時刻掌握各項服務的健康狀態,並非易事。雲原生時代這一領域內湧現出了諸多解決方案。本元件對可觀察性當中的重要支柱遙測與監控進行了抽象,方便使用者與既有基礎設施快速結合,同時避免供應商鎖定。
## 安裝
### 通過 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_interval`: 預設指標推送週期,單位為秒,下同。
```php
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 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_interval' => env('DEFAULT_METRIC_INTERVAL', 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_interval' => env('PROMETHEUS_PUSH_INTERVAL', 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_interval`。只建議離線任務使用推模式。
因為基礎設定的差異性,可能以上模式都無法滿足需求。本元件還支援自定義模式。在自定義模式下,元件只負責指標的收集,具體的上報需要使用者自行處理。
```php
'mode' => Constants::CUSTOM_MODE
```
例如,您可能希望通過自定義的路由上報指標,或希望將指標存入 Redis 中,由其他獨立服務負責指標的集中上報等。[自定義上報](#自定義上報)一節包含了相應的示例。
#### 配置 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_interval' => env('STATSD_PUSH_INTERVAL', 5),
'sample_rate' => env('STATSD_SAMPLE_RATE', 1.0),
],
],
];
```
StatsD 目前只支援 UDP 模式,需要配置 UDP 地址 `udp_host`UDP 埠 `udp_port`、是否批量推送 `enable_batch`(減少請求次數)、批量推送間隔 `push_interval` 以及取樣率 `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_interval' => env('INFLUXDB_PUSH_INTERVAL', 5),
],
],
];
```
InfluxDB 使用預設的 HTTP 模式,需要配置地址 `host`UDP 埠 `port`、使用者名稱 `username`、密碼 `password`、`dbname` 資料表以及批量推送間隔 `push_interval`
### 基本抽象
遙測元件對常用的三種資料型別進行了抽象,以確保解耦具體實現。
三種類型分別為:
計數器(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
<?php
declare(strict_types=1);
return [
'http' => [
\Hyperf\Metric\Middleware\MetricMiddleware::class,
],
];
```
### 自定義使用
通過 HTTP 中介軟體遙測僅僅是本元件用途的冰山一角,您可以注入 `Hyperf\Metric\Contract\MetricFactoryInterface` 類來自行遙測業務資料。比如:建立的訂單數量、廣告的點選數量等。
```php
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Model\Order;
use Hyperf\Metric\Contract\MetricFactoryInterface;
class IndexController extends AbstractController
{
/**
* @Inject
* @var MetricFactoryInterface
*/
private $metricFactory;
public function create(Order $order)
{
$counter = $this->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
<?php
declare(strict_types=1);
namespace App\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Metric\Event\MetricFactoryReady;
use Psr\Container\ContainerInterface;
use Redis;
class OnMetricFactoryReady implements ListenerInterface
{
/**
* @var ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container)
{
$this->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)。
### 自定義 Histogram Bucket
> 本節只適用於 Prometheus 驅動
當您在使用 Prometheus 的 Histogram 時,有時會有自定義 Bucket 的需求。您可以在服務啟動前,依賴注入 Registry 並自行註冊 Histogram ,設定所需 Bucket 。稍後使用時 `MetricFactory` 就會呼叫您註冊好同名 Histogram 。示例如下:
```php
<?php
namespace App\Listener;
use Hyperf\Config\Annotation\Value;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Framework\Event\BeforeMainServerStart;
use Prometheus\CollectorRegistry;
class OnMainServerStart implements ListenerInterface
{
protected $registry;
public function __construct(CollectorRegistry $registry)
{
$this->registry = $registry;
}
public function listen(): array
{
return [
BeforeMainServerStart::class,
];
}
public function process(object $event)
{
$this->registry->registerHistogram(
config("metric.metric.prometheus.namespace"),
'test',
'help_message',
['labelName'],
[0.1, 1, 2, 3.5]
);
}
}
```
之後您使用 `$metricFactory->makeHistogram('test')` 時返回的就是您提前註冊好的 Histogram 了。
### 自定義上報
> 本節只適用於 Prometheus 驅動
設定元件的 Promethues 驅動工作模式為自定義模式( `Constants::CUSTOM_MODE` )後,您可以自由的處理指標上報。在本節中,我們展示如何將指標存入 Redis 中,然後在 Worker 中新增一個新的 HTTP 路由,返回 Prometheus 渲染後的指標。
#### 使用 Redis 儲存指標
指標的儲存介質由 `Prometheus\Storage\Adapter` 介面定義。預設使用記憶體儲存。我們可以在 `config/autoload/dependencies.php` 中更換為 Redis 儲存。
```php
<?php
return [
Prometheus\Storage\Adapter::class => Hyperf\Metric\Adapter\Prometheus\RedisStorageFactory::class,
];
```
#### 在 Worker 中新增 /metrics 路由
在 config/routes.php 中新增 Prometheus 路由。
> 注意若要在 Worker 下獲取指標,需要您自行處理 Worker 之間狀態共享問題。方法之一就是將狀態按上文所述方式儲存於 Redis 。
```php
<?php
use Hyperf\HttpServer\Router\Router;
Router::get('/metrics', function(){
$registry = Hyperf\Utils\ApplicationContext::getContainer()->get(Prometheus\CollectorRegistry::class);
$renderer = new Prometheus\RenderTextFormat();
return $renderer->render($registry->getMetricFamilySamples());
});
```
## 在Grafana建立控制檯
> 本節只適用於 Prometheus 驅動
如果您啟用了預設指標,`Hyperf/Metric` 為您準備了一個開箱即用的 Grafana 控制檯。下載控制檯 [json 檔案](https://raw.githubusercontent.com/hyperf/hyperf/master/src/metric/grafana.json),匯入 Grafana 中即可使用。
![grafana](./imgs/grafana.png)