Kotlinに書き換えたPerlプロダクト「LINEポイントクラブ」

大原康平氏:「8年続くPerlプロダクトをKotlinに書き換えた話」と題して、開発4センターの大原が発表いたします。本日のアジェンダに入る前に、私について紹介いたします。大原といいます。新卒2018年入社です。現役でPerlやKotlinのコードを書いています。

アジェンダです。まず、今回Kotlinに書き換えたPerlプロダクトである「LINEポイントクラブ」について紹介します。そのあと、なぜPerlをKotlinに書き換えたのかを説明して、書き換え後のシステムオーバービューをお見せします。

そして、プロジェクトをどのように進行したのかについて簡単に紹介します。最後に、プロジェクト中に発生した難しさや知見、そして別言語に書き換えるメリットについて話します。

今日のこのセッションの話を最後まで聞くと、移行プロジェクトの全貌がわかります。新規サービスを開発している人は、自分は関係ないと感じるかもしれませんが、その今作っているシステムも必ず古くなります。なのでこのセッションは、システムを開発している人、全員に当てはまる話です。なので、よかったら聞いて行ってください。

「LINEポイントクラブ」とは

まず今回、PerlからKotlinに書き換えたプロダクトである、LINEポイントクラブについて紹介します。

LINEポイントクラブは、LINEアプリのウォレットタブにあるポイントクラブアイコンをタップするとアクセスできます。「LINE Pay」での支払いやLINEの各種サービスで使える共通ポイントであるLINEポイントを貯められる、さまざまなミッションの提供や連携サービスでの利用を案内するポータルサービスです。LINEポイントクラブは、2013年6月に「LINE フリーコイン」としてサービスを開始しました。

LINEポイントクラブには、「貯めるタブ」と「使うタブ」があります。「貯めるタブ」では、ポイントを貯められます。動画を見たりアプリをインストールしたりすることでポイントが貯められます。

「使うタブ」では、ポイントを交換できます。例えば「LINE マンガ」のコインやMUSICクーポン、その他さまざまなものに交換できるので、ぜひ利用してください。

トラフィックについて話します。平均的には秒間700リクエスト、ピーク時には秒間1万5,000リクエスト、デイリーでは約5,700万リクエストといった感じになっています。ただしリクエスト数については、適当な期間を選んで出した値なので、画面で見せた数字よりも多い日や少ない日もあります。

Perl時代のサーバー側のシステム構成

Perl時代のサーバー側のシステム構成の図を簡略化した図です。上のほうがインターネットです。外からリクエストが来ると、ロードバランサーで受けて、「nginx」で「貯めるタブ」と「使うタブ」のアプリケーションへそれぞれプロキシします。「貯めるタブ」と「使うタブ」で別々のデータベースを持っており、それぞれのアプリケーションがコンテンツを返す構成です。

「貯めるタブ」がPerlで、「使うタブ」がKotlinで書かれています。なぜ言語が違うのかというと、「貯めるタブ」が2013年からサービス開始したのに対して、「使うタブ」は、2015年の4月からサービスを開始したという歴史があったためです。ちなみに、2015年4月にサービス開始した当初、使うタブはJavaで書かれていたのですが、2020年にKotlinに書き換えています。

言語が違う2つのアプリケーションを管理する大変さというのがあって、エンジニアリソースの配分や、「貯めるタブ」と「使うタブ」で同じ機能をそれぞれ開発する必要があるという大変さがありました。

「貯めるタブ側」のシステム構成

このセッションでは、Perlプロダクトである「貯めるタブ」を書き換えた話がメインなので、「貯めるタブ側」についてもう少し説明します。

「貯めるタブ側」のシステムオーバービューを少し詳細にしたものがこちらです。1つずつ紹介していきます。

まず、media、admin、cv-workerというアプリケーションが「Amon2」というPerlのフレームワークで書かれています。

そして、HBase gatewayと書いているアプリケーションが、Kotlin/Javaで書かれていて「Spring Boot」というフレームワークを使っています。

ここで、「あれ? Perlプロダクトと言っていたのに、Java/Kotlinがすでにあるんじゃん」と感じた方がいると思います。これには歴史的な理由があって、PerlからHBaseを直接使えなかったということがありました。なので、PerlからHBase gatewayを使ってHBaseを操作していました。このHBaseの問題については、別言語に書き換えた理由を話すセクションでも触れます。

オーバービューに戻ります。図のMySQL for job queueの部分について話します。ユーザーが、「貯めるタブ」で動画を視聴するなどの、ポイントを獲得するための条件を達成すると、コンバージョンのデータをジョブキューにエンキューしていきます。ジョブキューはMySQLのテーブルに溜められていって、cv-workerが処理する構成でした。

最後に、ほかにもデータベースとしては、MySQLやキャッシュDBとして「Redis」や「Memcached」を使っていました。

PerlをなぜKotlinに書き換えたのか

ここから、PerlをなぜKotlinに書き換えたのかという話をします。そもそも、「なぜKotlinなのか?」という理由なのですが、その理由はシンプルで、会社でサーバーサイドの開発で最も使われている言語がJava/Kotlinだからです。隣のチームも、ほとんどJava/Kotlinで書いています。

同じ言語を選択すると、エンジニアリソースの配分や社内のエコシステムを使う上で、かなりのメリットがあります。それなのでJava/Kotlinを選びました。では、なぜJavaを選ばなかったのかというと、チームで開発しているほかのプロダクトと技術セットを合わせたかったから、という理由です。

PerlをKotlinに書き換えることに決めた理由を話します。まず、システムの構成が複雑化していました。これについては、Perlのシステムのオーバービューをお見せした時にも話したように、「貯めるタブ」と「使うタブ」が別言語で実装されていたり、PerlがHBaseを使うためのゲートウェイアプリケーションを管理する必要があったりしました。

2つ目に、8年間さまざまな機能が追加・変更・削除されたことにより、機能自体も複雑化していました。すでに使われていない機能もたくさんありました。

3つ目に、Perlエンジニアの少なさゆえ、いずれ開発続行が不可能になる未来が見えていました。

4つ目に、プロジェクト開始前の段階で、直近半年くらいは大きな変更はなさそうだったので、取り組むなら今だとなったわけです。これはポジティブな理由でした。

5つ目に、Perlのライブラリをメンテナンスする人口が減ってきていて、最近のミドルウェアに対するクライアントライブラリが豊富とは言えなくなってきています。例えばHBaseは、何年か前にPerlから使おうと挑戦したことがあって、クライアントライブラリが、当時よく動くものがなくてThriftを使って、HBaseを使おうとしたりとかいろいろ試したのですが、私たちが望むような動作をしませんでした。

そして結局、HBase gatewayアプリケーションをJavaやKotlinで実装しました。RedisクラスタもPerlからだとうまく扱えませんでした。

ここで補足なのですが、私はPerlは好きなので、Perlのことを悪く言うつもりはまったくありません。私たちのケースにおいて、当時望む結果が得られなかったということであって、時間が経った今試した場合や別のプロダクトで使う場合には、うまく動くかもしれません。

Kotlinに書き換えたあとのシステム構成

Kotlinに書き換えたあとのシステムオーバービューです。簡単に書くと、こんな感じになりました。順番に話していきます。まず、すべてのアプリケーションがSpring Boot(Kotlin)で実装されています。

右下のデータベースは、過去に使っていた「貯めるタブ」と「使うタブ」のデータベースをそのまま使っています。

新しくなった部分について話します。アプリケーション間の通信は、gRPCで行うようにしました。知っている人には釈迦に説法になってしまいますが、Protocol Buffersでデータをシリアライズして高速に通信できることと、IDLで定義したAPI仕様からクライアント側とサーバー側でそれぞれコードを生成してくれるのが便利です。

ポイントクラブの貯めるタブのデータは複雑で、データのサイズが大きいものもあるので、そういったデータをアプリケーション間でやり取りする時に苦しまずに済んだのは、かなりメリットに感じました。

次に「Kafka」をジョブキューとして導入しました。Perl時代はMySQLを使っていました。Kafkaを使うことによってスケーラビリティが上がったことと、自前のジョブキュー管理の実装が不要になったことと、別のコンシューマを追加して別の処理もできるようになったことがメリットです。

HBaseについて話します。Perl時代に使っていたHBase gatewayアプリケーションが不要になり、管理コストが減りました。coreやcv-workerといったアプリケーションから直接HBaseを操作できるようになりました。

adminアプリケーションについて説明します。adminアプリケーションは、「貯めるタブ」のデータをmedia DBに取り込みます。そして、「使うタブ」のデータもmedia DBに取り込みます。つまり、media DBが「貯めるタブ」と「使うタブ」のデータの違いを吸収するような層になっています。

その結果、mediaアプリケーションは、「貯めるタブ」と「使うタブ」の両方のコンテンツを返せるようになりました。そして、mediaアプリケーションは、今後「Kubernetes」などにすることを見据えて、Redisクラスタにのみ接続することで、スケーラビリティが高い状態にしています。

プロジェクトをどのように進めたか

プロジェクトをどのように進めたのかという話に入っていきたいと思います。開発メンバーの構成を紹介します。6名のエンジニアで開発しました。3名がJava/Kotlinエンジニアで、3名がPerlエンジニア。Java/Kotlinエンジニアについては、Java/KotlinとSpring Bootの開発経験が豊富なメンバーです。Perl時代の「貯めるタブ」の仕様についてはあまり知らないです。

プロジェクトの初期は、Perlエンジニアも開発がスムーズに行えるように環境を整えてくれました。彼らなしではリメイクプロジェクトを完遂することは難しかったと思います。なので言語を書き換える時には、書き換え先の、今回で言うとKotlinのエンジニアが必要だということが認識できました。

Perlのエンジニアについては、「貯めるタブ」の仕様についてはおおよそ把握しています。プロジェクトの初期は、仕様を書くことを主に行っていました。

プロジェクト期間中のサービスの運営と企画について、どのような体制にしていたのか話します。

まず、旧システムには、新しい変更を加えないことを決定しました。変更があると、書き換え先のKotlinにも適用する必要があって、開発工数がかさみ、いつまで経っても書き換えが完了しないからです。これについては、プランナーや運用サイドのメンバーに理解してもらえたのが助かりました。

プロジェクト期間中、デイリーミーティングを開発側でやっていたのですが、プランナーにも参加してもらうことで、仕様の変更の決定を迅速にできたのでよかったです。

今回のプロジェクトのスケジュールは、ざっくりこのように進みました。まず、2021年、つまり今年の1月からプロジェクトがスタートしました。そして4月頃、coreアプリケーションの開発が完了しました。

coreアプリケーションというのは、先ほどお見せしたシステムオーバービューの真ん中上の、この緑のcoreの部分のことです。

スケジュールに戻りまして、8月にほかのアプリケーションの開発を完了しました。ほかのアプリケーションというのは、この緑のアプリケーションのことです。そして、8月から9月にかけて、インテグレーションとQAを行って、2021年9月27日にメイン部分をリリースしました。スケジュールについてはこのような感じでした。

後半へつづく