As a SW/Ops/DB Engineer

riywo’s technology memo

Fcache - File Cache for Parallel Processes

以前からたまーにこういうのがあるとうれしいケースがあるなぁと思ってたので作りました。

どういうものかというと、こういう感じで何かstdoutに吐き出すコマンドの前にfcache EXPIRE_SECというのを付け足して実行すると、初回はコマンドを実行して結果をファイルに保存しつつstdoutにも出力します。

$ fcache 10 curl -s example.com
hoge

次に、同じfcacheコマンドを叩くと、保存されているキャッシュファイルの時刻を見て、expire時刻を過ぎてなければ単にそのファイルの中身をstdoutに吐き出して終了します。

$ fcache 10 curl -s example.com # 実際はcurlは実行されない
hoge

expire時刻を過ぎていれば初回と同じ動きをしてキャッシュを更新してくれます。flockを使って、読み込みだけなら共有ロックで並列に、書き込みが発生する時には排他ロック、みたいな処理をしてます(が何分まともな排他制御書いたことないのできっとバグってます。。。)

何の役に立つの?

特に監視の処理の中で、ほぼ同時に並列で1つのAPIを叩く監視項目があった時に、みんなが同じAPIを叩くのは非効率だなぁと思った時に効果があります(つまりニッチ)。何も気にせずfcacheコマンドを並列に実行すれば、最初の人がAPIを叩いてキャッシュしてくれて、あとの人はキャッシュを利用してくれます。

例えばZabbixという監視ソフトにはUserParameterというagent側でコマンドを実行して数値を返す、みたいなのが定義できます。

$ curl -s localhost
aaa 1
bbb 2
ccc 3

$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key[*],curl -s localhost | grep $1 | cut -f 2

上の様な設定をしたサーバがあったとすると、zabbix_getaaa,bbb,cccの値が取れます。

$ zabbix_get -s server -k example.key[aaa]
1
$ zabbix_get -s server -k example.key[bbb]
2
$ zabbix_get -s server -k example.key[ccc]
3

ただし、これだと3回curlが呼ばれます。もしcurlを減らしたいなら、1つのitemでスクリプトを実行してその中で1回だけcurlしてから全てのキーについてzabbix_senderで送る、とかも考えられます。

$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key,/path/to/script # 中でzabbix_senderを複数実行

fcacheを使うとシンプルに実現できます。これならキャッシュの有効期間中はcurlは叩かれませんし、configも素直です。

$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key[*],fcache 10 curl -s localhost | grep $1 | cut -f 2

おわりに

適当に作った上に、自分で使ってるわけでもないので自己責任でご利用下さい。こういうコンセプトがあってもおもしろいよねという提案がしたかったのと、ちょうどpythonの勉強がしたかったので、自分的には満足です。

Comments