DL数2,700万以上を誇る「LINEマンガ」

山本一成氏(以下、山本):LINEマンガの開発全体を見ている山本と申します。よろしくお願いいたします。私からは、主にこの5つについてお話したいと思います。

まずはLINEマンガについて、簡単に紹介いたします。LINEマンガ自体はもともとはLINEのファミリーサービスで、2013年4月にサービスを開始しました。今はLINE Digital Frontierという会社に分社化しまして、独自の会社としてサービスを運営しています。

サービス規模については、こちらに記載したとおり、2020年4月1日時点の数字で、ダウンロード数2,700万以上(8月には3000万を突破)、決算高が2019年度で249億円、そしてトータルのリクエスト数が1日に約8億、RPS(Request Per Second)はだいたいピークで1万7,000リクエスト程度のサービスとなっています。

こちらに記載はありませんが、だいたいDUBで360万以上あり、多くの方に使ってもらっている、けっこう大きなサービスであると自負しています。

開発チームとUITチームとData Scienceチーム

続きまして、開発組織について紹介します。まずサービス開発室という大きな室がありまして、その中に主にサービスの開発を行う開発チームと、フロントエンドを担うUITチームがあります。

また、ちょっと見慣れないかもしれませんが、Data Scienceチームという、主にデータを分析して戦略を立てるチームも、サービス開発室の下にいます。データを非常に大事にするサービスですので、開発チームといかに効率的にデータを取れるかを連携するために、同じ室にチームがあります。

サービス開発室の開発チームのメンバー構成は、現状このとおりの人数構成になっています。事業規模に対しては非常にミニマム、よく言えば少数精鋭な体制になっていて、サーバーサイドが6名、Androidのメンバーが3名、iOSが4名います。非常にミニマムな体制なので、みなさんのちからをぜひお借りしたいと思っているところであります。

エンジニアのレベル定義は主に2軸

続きまして評価軸に関して説明します。まずLINE Digital Frontierの福利厚生であったり評価体制は、LINE側からほぼすべて受け継いでいて、エンジニアのレベル定義は主に2軸で展開しています。

まず左側にIレベルというものが見えるかと思いますが、こちらがプレイヤーとしてのキャリアになります。I1からI7まであって、上に行くほど上のレベルになっています。右側がMレベルになっていて、こちらはどちらかというとマネジメントよりのキャリアです。

エンジニアは2軸に分かれていると思いまして、そのままプレイヤーとして技術の向上を目指していきたいという方と、マネジメントとして組織、チームの能力を最大化していきたいという方がいると思うので、LDFではこのような2軸の評価体制で進めています。

勤務時間は完全に裁量労働制

続いてワークスタイルについて。まず勤務時間ですが、ほぼ完全に裁量労働制を取っています。自分の割り振られた仕事が完了していれば、短い時間で業務される方もいますし、決してブラックということではなく、自分たちの働きやすい働き方で働けるような体制となっています。

現状は、ご存知のとおりこういう状況なので、リモートの勤務体制になっています。現状は年内いっぱいまでこの体制で続けていく予定になっています。ただ、決してリモートだけということではなく、必要に応じて出社することも可能です。でもエンジニアの場合はほぼリモートで済んでいる状況なので、リモートで働かれている人がほとんどですね。

柔軟な働き方を模索中なので、状況によって変わる可能性はありますが、現状はこういうかたちになっています。

開発フローについて紹介します。LINEマンガでは、アジャイル開発の手法を取り入れています。アジャイル開発というとスクラムが有名ですが、もちろんスクラムのチームを組んでスクラム開発を進める場合もあれば、通常どおりにアサインして、長期に渡るようなプロジェクトでも、アジャイルでそのときの現場メンバーたちがアイデアを渡し合って進めていくような開発スタイルをとっています。

通常の開発フローは、エンジニアも関わりながら企画から計画を立てて、そこから設計/開発をして、そのあとに実際に品質として問題ないかのチェック(QA)を行ってから、リリースという体制を取っています。

リリーススパンとしては、現状だいたい1ヶ月に1回程度で行っている状況で、こちらは今後はもっと短いスパンでもできるような体制を模索していきたいと思っています。また、テストを非常に大事にしていまして、基本的にはユニットテストを必ず書くようにしています。

やはり何かしら長く続けているサービスだと、リファクタリングが必要になってくるので、そういう場合には、テストがないと動作担保がなかなか難しくなるため、テストはきちんと書く体制になっています。また、各チーム同士でコードレビューも当然行っていて、チームによっては3つ以上のApprove(承認)をもらえない限りは、マージできないルールにして、品質を担保するように努力しています。

あとはミーティング。こちらに書きましたが、開発全体で行うウィークリーの定例がだいたい1週間に1時間。また企画や運用メンバーと一緒に行う企画開発定例が1週間に1時間。

あとはリモート勤務体制になってから導入しましたが、デイリーミーティングといって、毎日本当に短い時間で、それぞれ本日行うタスクや困っていることを簡単に共有するようなミーティングを、1日15分ほど行っています。あとは各担当のサーバーであったりiOS、Androidの週間定例が、だいたい1時間とか、長いときで2時間程度とってやっています。

ミーティングをこう見ると、多いと感じるかもしれませんが、すべての時間を使うわけではなく、この中でなるべくコンパクトに行っていて、デイリーミーティングなどは、リモートの体制で状況を共有しています。周りの人がどういうことをしているのかが見えにくかったり、あとはやはり1人で作業されている人が非常に孤独な状況になったりということを聞いているので、そういうことがないように、朝にコミュニケーションを取っていける体制にしています。

私たちが本当に大事にしている3つのこと

最後にエンジニアカルチャーについて。カルチャーというか、私たちが本当に大事にしているものとして、今回は主に3つのものを紹介しようと思います。

私たちが大事にしているものの1つ目は、ユーザーファーストです。私たちのサービスを常に一番支えてくれているのはユーザーですので、常にユーザーニーズを意識した機能開発であったり、安定的にサービスを継続することを意識して業務にあたっています。

次にデータドリブン。私たちは本当に何か機能を作るときや戦略を練るときには、常にデータを見るようにしていまして、基本的には本当の真実はデータの中にしかないというのを私たちはモットーにしています。すべての判断基準はデータという行動理念で、私たちは業務をしています。

3つ目はTake Ownership。私たちは基本的にエンジニアとして決まったことを実装するだけでなく、しっかりと自分事として関係各者と議論して、よりよいサービスを目指す。言われたものを作るのではなくて、しっかりと考えて自分たちが責任をもって、よりよいものを作っていくという姿勢で、サービスの開発を行っています。

ざっとになりましたが、以上になります。

サーバーサイド・エンジニアのお仕事

小澤正幸氏(以下、小澤):ここからは、小澤がサーバーサイドのエンジニアとして、最近やった仕事を紹介いたします。

その前に軽く自己紹介しますと、17年目ぐらいのエンジニアで、大学のころからJavaとPerlを使っています。これはあとの話でもつながりますが、2010年にJavaの会社を経てからPerlの会社であったライブドアに入社しまして、それがLINEになったという経緯を経ています。

ライブドア/LINEでは、一貫してサービスの開発のエンジニアをやっていまして、こちらに挙げたようなLINE BLOGやLINE NEWS、それからLINEキャリアという転職情報サイトを経て、今はLINEマンガの開発に務めています。フルスタックでアプリを作っていた時期もありますが、どちらかというとサーバーサイドを一貫して見てきた感じです。

最近の働き方は、2月からずっとリモートで、こんな感じで家にいろいろ買い込んで環境も整えて、キーボードにもちょっと凝っていたりする状況です。

サーバーサイド仕事全般の話

本題を話す前に、サーバーサイドの仕事全般の話をさせてください。全体にざっくりとどんなことをやっているかというと、まず新機能の設計開発はやっています。それから既存の機能を変更したり追加したり改良・改修したり。

サービス運用という面も見ていまして、障害の対応もしますし、場合によっては調査したり、カスタマーサポートからの問い合わせに対応したりとか、インフラを見たり、技術負債を返したりすることもあります。今回は、この太字にした、使っている技術を随時アップデートしないといけないところについて話をしようと思います。

PerlからJavaへ

本題ですが、Kafkaによる分散処理の導入と新刊配信通知のJava移植について。PerlからJavaへ、JVMと書きましたが、まずはPerlのことを話させてください。ラリー・ウォールという人が作った言語で、いわゆるLL言語、スクリプト言語です。悪く言う人は「実行可能なノイズ」なんて言う人もいるんですけど。

ライブドアは、私が入った2010年ごろはPerlの会社でした。CPANというのは、JavaでいうとMavenみたいなオープンソースのモジュールを登録するリポジトリで、そこに有名なモジュールを書いている人や、YAPCという年1回のPerlのカンファレンス、で名を馳せた人がいっぱいいる会社でした。

2010年代にLINEとなって、そのころのLINEの関連サービスのことを私たちはファミリーサービスと呼んでいますが、その開発をけっこうライブドアの出身者が担っていました。けっこうスケジュールもタイトで、そうするとどうしても開発言語にPerlが選択されて、こちらに並べたようなLINE NEWSやLINEマンガ、LINE BLOG、LINEポイントがPerlで作られて、そのころはよかったのですが、2010年代半ばから急に他の言語に人気を取られて、採用が難しくなっている状況が正直なところです。

そうすると「Javaに移して行きたいね」となって、例えばマイクロサービス的な設計をして新しく作るサービスはJavaで、今まで作ったものもJavaに移植を進めていこうとなりました。私たちはトレンドとして「どうせならKotlinにしたいよね」というので、Androidではかなり前から進んでいましたが、最近はサーバーサイドもKotlinでやっていこうと思っています。

土台作り

そのために私がLINEマンガにジョインしまして、土台作りを進めました。ちょっとその手前で、何人かがSpring BootのWebアプリケーションを作って、MyBatisをORMに使ってデータベースに接続するようなことをやっていましたが、私が入ってからいろいろ整備をしました。

例えばブランチポリシーとか、CI、デプロイ周り。それからDockerを使ったローカル開発を作れる環境を整えたり、あとはPerlでのコードももちろんあるのでそちら側でデータベースを変更したり、Javaのほうでも変更することがあるので、その辺の段取りを整えたり。

あとはバッチサーバーがよく見たらないので作ったりしていました。あとは、これからお話しします、KafkaのProducerやConsumerを作ったりしていました。

PerlとJavaの技術スタックはよく聞かれるところなのでちょっと上げておくと、Perlは昔でいうLAMP構成です。あとはApacheはnginxのほうが主流で、今はそっちを使っています。Javaでは、ハードウェア的なところはLAMPと同じようにLinuxやnginxとMySQLなんですけど、フレームワークはSpring Bootをよく使っています。

インフラについては、LINE社内で共通化されているものがありまして、仮想マシン環境でデータベースを立ち上げたり、RedisやObject StorageといったAWSによるようなものが、だいたい内製のものでひと通り使えたりします。

Kafkaによる分散処理

Kafkaによる分散処理についてお話しします。ちょっと大雑把におさらいしますが、並行処理、並列処理、分散処理があり、ここで言っているのは並列処理を分散処理でしていきたいというお話しです。

Perlではどういうことをやっていたかを言うと、Perlは並列処理としてスレッドがあまり使われません。ないわけではないのですが、UNIXにある、forkの仕組みを使いやすくする「Parallel::ForkManager」というモジュールがよく使われていました。分散処理に関してはTheSchwartzというMySQLをキューに使うジョブキューが昔から実績があり使われていて、そこに仕事を投げると、そこにぶら下がっているワーカーがジョブを取り合って捌いてくれるという仕組みがありました。

それに対してJavaでは、Apache Kafkaというのをよく使っています。これはちょっと細かくお話したいところですが、時間の都合もあるので、弊社の河村という者が社外向けに発表していますので、こちらを詳しく見てもらえればと思っています。

Apache Kafkaには、Producer/Broker/Consumerというのがあって、ProducerがBrokerにメッセージを投げると、Consumerが読み取って処理します。それは、先ほどのTheSchwartzのようなキューで仕事を捌くのにも使えますし、いわゆるPub/Subの、通知をいろいろな人が読み取るというような用途にも使えます。これをLINEアプリ用に構築されたBrokerクラスタがあって、他のサービスもこれをインフラとして使える状況になっているので、LINEマンガでもそれに対応しました。

Producerに関しては、JavaとPerlの両方のコードからメッセージをプロデュースできます。JavaはSpring KafkaのKafkaTemplate、PerlはlibrdkafkaというCのライブラリがありますが、これをラップするCPANモジュール「Kafka::Librd」を使って、そのあたりを作っています。

Consumerは、新しく作るものはJavaがいいよねということがあったので、JavaにSpring Kafkaの@KafkaListenerを使ってConsumerを作れるようにして、それを16台ぐらいで捌ける仕組みを作りました。私は1つ前の案件で似たようなことをやっていたので、それを流用しています。

新刊配信通知のJava移植

そうやって土台ができた上で、実際にやっているものをこちらに移していくなかで、新刊配信通知のJava移植を私がやりましたので、紹介します。新刊配信の通知とは何かというと、日々新しいマンガがどんどん出てくるわけですが、それを前の刊を買ったり読んだりしている人に「新しいのが出たよ」とアプリに通知してあげる機能です。

Perl版ではどういうことをやっていたかというと、1台のサーバーで並列処理していました。1台の中で捌いている感じですね。誰に何を送るかを判定して、ユーザーごとに送っていきます。これが多い日だと6時間ぐらいかかることもあって、早くしたいということが課題となっていました。これをどんどん移植していくということを私がやりました。

何からやったかというと、まずは今のコードを読む。どう移植するかを考えます。そのときに、こんなふうに図を起こして、今どんな感じで動いているかを把握したあと、移すならこうかなといったシーケンス図も書いたりして、前半は、同一サーバーで並列処理をして、後半をKafka Consumerに分散処理させる方針を決めました。

その方針を決めてからは、移植の作業です。どんどんJavaに書き換えていきます。ただ元がPerlのコードということもあって、同じように1行1行逐次的にというよりはリファクタリングをしながら移していく感じになっていきました。だいたい2、3,000行ぐらいだったと思いますが、なかなか大変でした。

それが終わったあとにテストを書きました。開発環境にデータを用意しにくいという事情があって、自動のテストでできるだけバグをちゃんと潰すことにしました。まずPerlのコードにもテストがあったので移植して、リファクタリングもしていたので、そういったクラスにはユニットテストを用意しました。

それが終わったあとに、BETA環境に段取りを整えて、新刊のデータを用意して通知が届くかを検証。これは自動テストをがんばって書いた甲斐もあって、数日で完了しました。

じゃあ本番に投入できるかというと、なかなかいきなりは怖いので、検証実行モードを作りまして、誰に何を送るかを計算までやって、Kafkaに流すところまではやるりながら、実際に送信する手前で止めておき、ログを書き込むだけにするということをやりまして、Perl版の実装と両方動かしてどうなっているか、どのくらい時間がかかっているのかを調べたりしました。

大量に処理をしていると、その時点で出るエラーなんかもあったので、それを直したりして、同じように同じ人に同じ新刊を送っているのかをPerl側のログとJava側のログで比較しました。そうすると95パーセントぐらいは合っていて「よかったね」……というわけにはいきません。5パーセント、10パーセントでも、やはり10から20万人ぐらいはいて、それはけっこう大きい数なので、なんで差が出るのかを調べることにしました。

仮説として立てたのが、実行時間を重ならないようにズラしていたので、その間にユーザーがマンガを新しくお気に入りに入れると、あとで送ったほうだけが送信対象になるために起きたのではないかということ。またマンガを読んだ人には行き違いにならないように通知対象から外すというプログラムを入れていたので、この間に読んでいると通知は届きません。そのあたりを実際に原因調査するプログラムを書いて、ログを付け合わせて究明したところ、それで説明がついたので、よかったなという感じです。

実際にそれぐらい、けっこう夜中なんですけど動いていました。それで移植切替をして、8月8日より新しい実装で動いていまして、だいたい6時間ぐらいかかっていたのが2、3時間で、要は倍ぐらいの速さで終わるようになりました。これで事例紹介は終わりです。

こういう人が向いている

実感として思うところは、技術とか言語で得意でできることがあるのはもちろん大事ですが、その上で新しいものが出てきたらちゃんとそこに向き合える人。それから自力でそういうことが動ける人。あとエンジニアリングも大事なんですけど、サービスとユーザーのために動ける人とかが向いているんじゃないかなと思っていますので、ぜひそういった方と自負される方のご応募をお待ちしています。

ご清聴ありがとうございました。