helen's blog

ずっとおもしろいことしてたいな。

mackerel-plugin-varnishのグラフを読めるようになりたい

Varnishをやっていて悩むことがよくあって
mackerel-plugin-varnishを使ってみようと思い立ってすぐ入れたけど
あまりリファレンスややってみた記事がヒットしなかったのでざっくりまとめました😁

キャッシュサーバやVarnishを自分で構築するのも監視するのも初めてなので
お手柔らかにお願いします...🙏

今回使った環境

  • CentOS7.5
  • mackerel-agent 0.56.0
  • Varnish 6.0
  • プロキシ先は同ホストに立てたPHPのWebアプリケーション
    • 今回はあまり重要ではないので詳細は割愛します

Varnishとは?

Varnish HTTP Cache — Varnish HTTP Cache

キャッシュするHTTPリバースプロキシ(直訳)で
6.0.0は2018年3月にリリースされたものです
語り始めると長いのでVarnishについては気が向いたら別で書きます

mackerel-plugin-varnish

github.com

VarnishにはvarnishstatというVarnishのパフォーマンスを見れる便利ツールがあり
mackerel-plugin-varnishはvarnishstatの出力した結果をMackerelへ投稿してくれます
varnishstatはVarnishをインストールすると一緒にインストールされます

varnishstatを実行するとこのような画面になります
引数に-1で今の瞬間のデータ表示、つけない場合は最新のものが常に表示されます
※長いので関係する箇所だけ抜粋しました

# varnishstat -1
MAIN.client_req           103036        10.97 Good client requests received
MAIN.backend_req              10         0.00 Backend requests made
MAIN.backend_conn              4         0.00 Backend conn. success
MAIN.backend_unhealthy         0         0.00 Backend conn. not attempted
MAIN.backend_busy              0         0.00 Backend conn. too many
MAIN.backend_fail              0         0.00 Backend conn. failures
MAIN.backend_reuse             6         0.00 Backend conn. reuses
MAIN.backend_recycle          10         0.00 Backend conn. recycles
MAIN.backend_retry             0         0.00 Backend conn. retry
MAIN.client_req           103036        10.97 Good client requests received
MAIN.cache_hit            103025        10.97 Cache hits
MAIN.cache_hit_grace           0         0.00 Cache grace hits
MAIN.cache_hitpass             0         0.00 Cache hits for pass.
MAIN.cache_hitmiss             0         0.00 Cache hits for miss.
MAIN.n_object                  3          .   object structs made
MAIN.n_objectcore            153          .   objectcore structs made
MAIN.n_objecthead            153          .   objecthead structs made
MAIN.n_expired                 7          .   Number of expired objects
SMA.s0.c_req                  30         0.00 Allocator requests
SMA.s0.c_fail                  0         0.00 Allocator failures
SMA.s0.c_bytes            368834        39.28 Bytes allocated
SMA.s0.c_freed            196382        20.92 Bytes freed
SMA.s0.g_alloc                15          .   Allocations outstanding
SMA.s0.g_bytes            172452          .   Bytes outstanding
SMA.s0.g_space         268263004          .   Bytes available

これを目で追うのが大変だけど、
Mackerelを使うとデータを蓄積して
見やすく表示して監視してくれるのが本当にありがたいです

プラグインを実行すると上記の出力がこうなります

# mackerel-plugin-varnish
[SMA.s0.g_alloc s0 g_alloc]
varnish.requests.requests	13020.000000	1534141634
varnish.requests.cache_hits	13020.000000	1534141634
varnish.backend.backend_req	0.000000	1534141634
varnish.backend.backend_conn	0.000000	1534141634
varnish.backend.backend_fail	0.000000	1534141634
varnish.objects.n_object	1.000000	1534141634
varnish.objects.n_objectcore	151.000000	1534141634
varnish.objects.n_objecthead	151.000000	1534141634
varnish.objects_expire.n_expired	0.000000	1534141634
varnish.busy_requests.busy_sleep	0.000000	1534141634
varnish.busy_requests.busy_wakeup	0.000000	1534141634
varnish.sma.g_alloc.s0.g_alloc	5.000000	1534141634
varnish.sma.memory.s0.allocated	57231.000000	1534141634
varnish.sma.memory.s0.available	268378225.000000	1534141634

カスタムメトリック

pluginを読み込ませるだけで7個のグラフが生成されます
対象のvarnishstatのフィールド名と合わせて表にしました

Varnish Backend

BackendはVarnishがリクエストを受け取ったあとの転送先です
今回用意した環境で言うと「PHPのWebアプリケーション」がそれにあたります

Metrics 説明 varnishstatのフィールド名
Conn fail Backendとのコネクション失敗数 MAIN.backend_fail
Conn Success Backendとのコネクション成功数 MAIN.backend_conn
Requests Backendへのリクエスト数 MAIN.backend_req

このRequestsはアクセス数ではなくBackendへのアクセス数なので
サイトのアクセス数とは一致しません
クライアントのリクエスト数はMAIN.client_reqです
MAIN.backend_failが上がってくるようだと、
BackendのアプリケーションかVarnishとアプリケーションの疎通に問題がある可能性が高いです

f:id:heleeen:20180813190455p:plain

これはキャッシュをオフにしたときのグラフです
キャッシュをオフにするとRequestが増え、Conn Successがすこしだけ増えます

Varnish Busy Requests
Metrics 説明 varnishstatのフィールド名
wakeup sleep listから取り除かれたリクエスト数 MAIN.busy_wakeup
sleep Busy状態のオブジェクトがあるのでsleepさせたリクエスト数 MAIN.busy_sleep

Varnishでは、リクエストがバックエンドに到達するとbusyオブジェクトが生成されます
この処理中に新しいリクエストが同じページに来たときに
Varnishがbusyオブジェクトがある(同じページへのアクセスが処理中)と判断すると
そのリクエストを一度Waitingリストへ登録します
そして、最初のリクエストが処理されたときに
Waitingリストに登録されていたリクエストたちにもレスポンスします

つまり、Varnishは同じページへのリクエストがあるときは
最初の1つをBackendへ流し他は待機させておいて、
最初のリクエストが処理された後に、そのキャッシュを待機させていたリクエストに返すという動作をしています

その監視をしているのがBusyとWakeupです

Varnish Client Requests
Metrics 説明 varnishstatのフィールド名
Hit キャッシュヒット数 MAIN.cache_hit
Requests リクエスト数 結果 MAIN.cache_hit ?

HitがRequestsに近ければ
Varnishがキャッシュをユーザに返してくれていて
そのリクエストは裏のアプリケーションに到達していないことになります

f:id:heleeen:20180814152356p:plain

キャッシュをオフにした状態のグラフです
オフにしてもデフォルトのキャッシュである程度Hitはします
Hit率が低い場合、キャッシュ条件を見直すと高速化する可能性があります

f:id:heleeen:20180813160621p:plain

キャッシュ設定してこれくらいでした
特定ページへのabなのでHitsとRequestsが一致しちゃっておもしろくないですが
Hit率が高いので調子は良さそうですね😅
cache_hitpass(キャッシュしないキャッシュ)も見れるとうれしいけど
Mackerelのメトリックとしてないってことは見なくていいのかな?🤔

Varnish Objects
Metrics 説明 varnishstatのフィールド名
objecthead キャッシュ内でハッシュが異なるものの数 MAIN.n_objecthead
objectcore キャッシュ内のメタデータの数 MAIN.n_objectcore
object キャッシュしたオブジェクト数 MAIN.n_object

hashはここではキャッシュのKeyです
Varnishで"オブジェクト"というといろんな種類があり
その中のobjectcore, objectheadがモニタリングされています

f:id:heleeen:20180814153621p:plain

キャッシュをオフにした状態でのグラフです

Varnish Objects Expire
Metrics 説明 varnishstatのフィールド名
expire 期限切れしたオブジェクト数 MAIN.n_expired

f:id:heleeen:20180813190140p:plain

これはキャッシュをオフにして30秒おきにアクセスしたグラフです
キャッシュを作ってもすぐexpiredになっていまうので上がって下がってを繰り返します

MAIN.n_lru_nuked(新しいキャッシュのために強制削除されたキャッシュ)が
カスタムメトリックにはないのはなぜなのかが気になった
n_lru_nukedが起こるということはキャッシュ用メモリサイズがあっていないのかも?っていう監視は不要なものなのかな

Varnish SMA Allocations

SMAとはキャッシュのために確保したメモリ(MAlloc Stevedore counters)のことです

SMFやSMUなどがあるのですが
ここではMackerelが収集対象としているSMAのみにフォーカスします
端的にいうとキャッシュを何に保存しているか?です

Varnishの起動時に指定します
今回は検証なので

VARNISH_STORAGE="malloc,256M"

RAM使用の256MiBとしました
256MのMはmebibytesです
またオブジェクトごとに1 KiBを内部構造用に使用します

指定はMiBなのにvarnishstat -1したときはByteで表示される罠があります😂

Metrics 説明 varnishstatのフィールド名
num 未処理のストレージ割り当て数 SMA.s0.g_alloc

f:id:heleeen:20180814164411p:plain

キャッシュをオンにしてアクセスして放置すると
このように増えたり減ったりしてました

Varnish SMA Memory
Metrics 説明 varnishstatのフィールド名
Available ストレージの残りバイト数 SMA.s0.g_space
Allocated 割り当て済みバイト数 SMA.s0.g_bytes

使われれば使われるほどAvailableが減っていって
Allocatedが上限になります

グラフはByte表示されます

f:id:heleeen:20180814164656p:plain

キャッシュ対象が少ないため全然使われてないですが
きっとこれからAvailableとAllocatedが戦いを繰り広げてくれるでしょう!

参考サイト

Varnishと戦い始めての感想は、6系は特に実践記事は少なく、
数年前の記事にVarnishは対応していないので・・って書いてあっても
実はもうその機能実装されてたりするので、ひたすらリファレンス見てTryErrorしてます
その合間もMackerelが見ててくれるのはモチベーションにもなりますね💪

はてなブログ映えのために何度かabコマンド叩いてるけど怒られないといいなぁ😅