今年書いた & update したCPANモジュールたち

Perl Advent Calendar 2018 11日目のエントリです。

最近、新しく書きはじめるもので Perl を使うことはめっきり減っているのですが、それでも仕事のいくつかのプロジェクトのメイン言語が Perl だったり、リリースした CPAN モジュールでまだまだ需要があるものはメンテが必要です。

ということでちょくちょく Perl も書いているので、今年自分がリリースした CPAN モジュールと update の変更点をまとめておきたいと思います。

Fluent::Logger

おなじみ Fluentd へログを送信するためのモジュール。2011年にリリース以来、継続的にメンテナンスしています。2018年の変更は、エラー時に即座にリトリライするためのオプション追加でした。

  • 0.27 2018-06-19T07:52:56Z
    • Add retry_immediately option (#28)

これは、とあるプロジェクトで AWS NLB の配下に fluentd を配置していて、NLB が 360秒間通信がないとコネクションを切断してしまうので (普通の fluentd はそういう挙動はしない)、その場合のリトライが次のログ送信時まで遅延してしまうのを救済する意図で追加したものでした。

Redis::Setlock

Redis を使って排他ロックを取得するためのモジュールです。こんなエントリも書きました。 sfujiwara.hatenablog.com

社内の Perl のプロジェクトではよく使われていて、そこでの要求からいくつかの機能追加があります。

  • 0.12 2018-07-09T08:50:57Z
    • Set expire to a wait queue. (#6)
  • 0.11 2018-05-24T05:04:58Z
    • Add blocking option to lock_guard (#5)
  • 0.10 2018-05-24T04:23:50Z
    • Change an algorithm to build key name for $WAIT_QUEUE. (#4)
  • 0.09 2018-05-23T07:33:17Z
    • Add $WAIT_QUEUE package variable. (#3) When $WAIT_QUEUE is true, wait for a lock released using BLPOP command instead of polling

このモジュールは Redis のある key を SET NX で排他取得し、必要なくなったらその key を削除することでロックを解放します。

ロックが競合した場合、あとにロックを取得しようとしたプロセスは 500ms 間隔のリトライで再度取得を試みるのが従来の実装でしたが、それでは解放待ちに時間が掛かりすぎるという課題がでました。そこで BLPOP を利用した解放待ち queue を用意して、解放時に queue へメッセージを送信することで、待たされているプロセスは速やかにロックを取得しにいく、という挙動ができるようになりました。

Katsubushi::Client

memcached protocol でアクセスできる分散ID採番機 katsubushi へのクライアントモジュールです。

  • 0.2 2018-07-25T03:10:29Z
    • fork safe (#4)

fork safe、(作者からすると)嫌な (使う側とすると)嬉しい fix ですね。

とあるプロジェクトでベンチマークをしていたところ、妙に katsubushi からのID取得に時間が掛かることが発覚しました。その原因を追及したところ、内部で使っている Cache::Memcached::Fast は fork safe ではない!ということに気づいて解決したものです。

一度接続したあと fork した場合、fork したプロセスがひとつの接続を共有してしまいます。そのため、自分が投げたリクエストの結果を誰かに横取りされてしまって、なかなかレスポンスが返ってこない、というような現象が発生するのでした。

fork safe ではないことは、Cache::Memcached::Fast のドキュメント にも、ちゃんと書いてあります。

disconnect_all

$memd->disconnect_all;

Closes all open sockets to memcached servers. Must be called after "fork" in perlfunc if the parent process has open sockets to memcacheds (as the child process inherits the socket and thus two processes end up using the same socket which leads to protocol errors.)

AWS::XRay, Plack::Middleware::XRay, Devel::KYTProf::Logger::XRay

これは今年の新作です。

AWS X-Ray という分散トレーシングのマネージドサービスに、Perl のアプリケーションからトレースデータを送信するためのものです。

公式の Perl SDK は提供されていないため、じゃあ自分で書くしかないな、ということでえいやと書きました。

f:id:sfujiwara:20181027013112p:plain

sfujiwara.hatenablog.com

ちなみに Katsubushi::Client が妙に遅い(ことがある)、というのは X-Ray の解析結果から気がついたものでした。DB へのクエリなどとは違って通常遅くなることが考えにくい部分なので、X-Ray がなかったら原因にたどり着くのに相当時間が掛かっただろうなあという実感があります。おすすめです。

X-Ray 関係のモジュールについては、来年1月に開催される YAPC::Tokyo で、 「Perlでも分散トレーシングしたい! - AWS::XRayによる解析とその実装」というタイトルで 40分の発表をする予定です。 YAPC::Tokyo 2019 - TALKS

12月16日まで チケットも発売中のようです ので、興味のあるかたは是非聞きに来てください!

まとめ

あらためて振り返ってみて気がついたのですが、実はこれらの修正はすべて、とあるプロジェクトの構築中に負荷試験で明らかになった問題を解決したり、負荷試験結果を解析するために作られたものでした。必要は発明の母ですね。

それでは、良いお年を。