あんパン

こしあん派

1秒おきになんかする

ちょっと前の話だけど、社内のISUCON練習会で特定のエンドポイントが重いのをなんとかしようとしていた。このエンドポイントはキャッシュして問題ないので普段はキャッシュから返して1秒おきにリフレッシュしたい。Redisなどに入れてTTLを指定してキャッシュが揮発していたら再生成という手もあるが、これだとTTLが切れた瞬間わずかにリクエストが詰まってしまう。なので、何か別の手立てで定期的にキャッシュをリフレッシュしたい。

Goだとcarlescere/schedulerを使えば簡単にできそう。ただ、この回はPerlでやろうということで進めていた。AnyEventを使えばなんとかなる? と思いつつあんまり慣れていないライブラリを突然使うのはコストが高い。そんなときwatchを使えばいいじゃんということに気付いた。

systemdのunitファイルを以下のような感じで書いて systemctl start すれば良い。watchで1秒おきにcurlを起動してキャッシュの再生成エンドポイントを叩く作戦。

[Unit]
Description=Refresh cache every second

[Service]
Type=simple
Environment=TERM=linux
ExecStart=watch -n1 "curl -s http://localhost/refresh-cache"

[Install]
WantedBy=multi-user.target

watchはcurses的なやつが起動するので、 Environment=TERM=linux しておかないと Error opening terminal: unknown. というエラーが出る。

ところでsystemdにはtimerがあり、これも秒ごとに実行することができる。あとで思い出して試したところ、タイマーの精度が悪いのか実行が抜け落ちてしまうことがあった(AccuracySec=1us とかにしてもだめだった、なんででしょうね)。ということでwatchくらいが手軽でよさそうではないか。なかなか使うこともないだろうけれどメモ。


追記(2022-08-09):

1秒おきになんかする - あんパン

while true; do sleep 1; curl ….; doneとかはどうでしょう

2022/08/06 01:40
b.hatena.ne.jp

確かにwhileで回すのも良さそうですね。結果が標準出力に出るのでjournalctlなどで様子を観察しやすいのも良さそう。