2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
提供:LINE株式会社
リンクをコピー
記事をブックマーク
川田裕貴氏:今日は、LINE Messaging APIの中のServer Side Kotlinについてお話をしようと思います。まず、自己紹介をします。私は川田裕貴と言います。LINEに初めて関わったのは2014年の開発インターンシップからなのでけっこう長いのですが、新卒入社で入社しました。
Kotlinに関わり始めたのは2018年くらいからです。「LINE Things」というプロジェクトに参加した時にKotlinを初めて書いて、その年にオランダで行われた「KotlinConf」に参加しました。2019年からは、Messaging APIのサーバーサイド開発をしています。
1日20億以上のメッセージを送信するシステムですが、どんなふうにMessaging APIが動いていて、どんなふうにKotlinが使われているのか、中身の紹介をしたいと思います。
LINE Messaging APIを使ったことがある方も多いと思いますが、今日は知らない人もいると思うので一応紹介すると、LINEのBotを作るAPIやプラットフォームのことです。
LINEアプリは、ユーザー同士でコミュニケーションするという機能もありますが、LINE公式アカウントと言われているアカウントがたくさんあって、LINE NEWS、LINEの通訳Bot、お天気のBotなど、いろいろなものが提供されています。これらのLINE公式アカウントを作るためのAPIが、LINE Messaging APIです。
LINE Messaging APIには、メッセージをブロードキャストしたり、プッシュやリプライと言われている個別にメッセージを配信するAPIだったり、ユーザーからメッセージを受け取るためにBotに対してWebhookを送信していたり、さまざまな機能があります。
また、LINE公式アカウントの画面を開くと出てくる「リッチメニュー」や、どういうユーザーがこのメッセージを受け取ってアクションしたのか判別する機能や、ユーザーのメッセージ送信数を集計する機能など、すべてをまとめてMessaging APIとして提供しています。
どういうことをやっているのかを、簡単な図で説明したいと思います。LINEユーザーは、直接Messaging APIを使っていませんし、Botと会話しているわけでもありません。LINEユーザーは、talk-serverと言われる大きなLINEを司るコンポーネントに対して通信を行なっています。
ただしMessaging APIは、talk-serverのプロトコルとはまったく異なるAPIで通信しています。そこの橋渡し役が私たちのチームで開発しているMessaging APIのバックエンドサーバーです。
Messaging APIはAPIを直接使っているChatbotだけが利用しているわけではありません。LINE公式アカウントのWebから操作できる管理画面や、外部の会社で提供している「LINE WORKS」というアカウントもLINEの中で1つのBotとして動いています。
このような機能も、すべて私たちのMessaging APIのバックエンドを使っていて、実際のLINEユーザーはtalk-serverを経由してコミュニケーションしています。中身はたくさんのキューがあって、たくさんのマイクロサービスコンポーネントが集まっているシステムです。
実際にどういうところでKotlinが使われているのか。LINE Messaging APIには、ユーザーからBot側と、Botからユーザー側と、大きく2つの経路があります。まずはユーザーからBotへメッセージを送信した場合のフローを見ていこうと思います。
Webhook送信側のサーバー構成は、2020年から2021年に大幅に構成を刷新しています。刷新をする際にKotlinを積極的に採用したので、多くのコンポーネントがKotlinで動いています。
昔はtalk-serverの中で、実際にBotを1つのユーザーとして一般のLINEユーザーがAPIを呼んで、メッセージをフェッチしてWebhookを送信していたのですが、今はtalk-serverからLINEが処理するイベントをすべて受け取って、その中からBotに関するイベントを抽出して、そのイベントを処理しながらWebhookとして送信しています。
イベントは本当に多く、秒間で100万以上あります。LINEで取り扱うすべてのイベントを受け取り、大量のイベントの中からBotに関するイベントだけをフィルターするコンポーネントが最初にあります。
(スライドを示して)ここはJavaで、その先はすべてKafkaのキューを挟んでKotlinのシステムになっています。なのでみなさんがMessaging APIのWebhookを受け取る時に送出しているサーバーはすべてKotlinで書かれています。
中身はReactorやCoroutinesを使って非同期化もされていて、REST APIやApache Thriftなど、いろいろなAPIを使ってマイクロサービス化されて動いています。こちら側はかなりKotlinが使われています。
逆にメッセージ配信側はKotlinが使われているところが少なく、JavaやScalaで書かれています。これには歴史的な事情もあります。LINE公式アカウントは10年近く動いているサービスなので、かなり初期からあるコンポーネントも多く、JavaやScalaで書かれています。
api.line.meというドメインを叩くとつながるAPI Gatewayは、すべてJavaで書かれていますし、その先のメッセージ送信サーバーには、コンポーネントがさまざまあって、ブロードキャスト用のサーバーやナローキャスト用のサーバーなどありますが、JavaやScalaで書かれています。その先にRabbitMQがあって、配信処理サーバーはほぼScalaで書かれていて、talk-serverへ送信しています。
ただ、それらがそれぞれ使うマイクロサービスコンポーネントは、一部Kotlinで書かれていたりします。あとで説明しますが、これらのサーバーの中で使っているコモンモジュールみたいなものは、最近Kotlinで書かれるようになってきました。
今まさにこのメッセージ配信側の、Kotlinへの移行を計画中です。最近、LINEのコンポーネントはKafkaへどんどん移行しているので、JavaやScalaで書かれたコンポーネント、RabbitMQを使っている部分はKafkaや、Reactorや、Kotlinを使っていこうと計画をしています。
古いコンポーネントもJavaで書かれていますが、私たちはMonorepoという方式を採用しています。マイクロサービスはいっぱいありますが、実際のリポジトリは1つに統合されています。
サーバー、サービスのコードがたくさんありますが、それぞれの中で共通の部分が出てきます。私たちはGradleでリポジトリを全部管理していて、Gradleの中のモジュールがそれぞれマルチモジュールになっていて、:commonsというモジュールの下にKafka、Redis、Cacheなどのモジュールが合わさっています。
Webhook側の刷新の時に、共通モジュールを書き直したり追加したりしたので、この部分に関してはかなりの割合でKotlinが使われています。
Javaで書かれているコンポーネントからも新しく書いた:commonsモジュールが使いやすく、なにかの理由でちょっと書き換えなきゃいけない時にこちらのモジュールで書き換えているので、表面上はJavaで動いていても中身のモジュールはKotlinで書かれているというものもかなり多いです。なのでもうKotlinなしでは生きていけないシステムになっています(笑)。
私たちのチームの特徴として、Java、Kotlin、Scala、それぞれ使っているのですが、私はKotlinがちょうどいいと思っています。JavaはJava 9以降進化していていろいろ増えてきてはいますが、まだ言語の機能が追いついていません。
Scalaは、やはり機能が強力でFunctional Programingをやりたい方はとても使い心地がいいと思いますが、若干読みづらく、例えば先ほどのKotlinのコモンモジュールみたいなものをScalaで書いてしまった場合、Javaから呼ぶとどうしてもScala特有の型やオプションが特殊な扱いになってしまいます。
このあたりのやりとりが難しく、その点Kotlinだとほとんど気にならずに使えるので、Javaから置き換えていくにもちょうどいいです。学習コストという面でも、Scalaほどパラダイムが変わらないのかなという点で、ちょうどいい言語だと私たちは思っています。
Kotlinというと、みなさんCoroutinesを使うと思いますが、私たちのチームではあえてCoroutinesを使わずに、非同期化しているところもあります。主にReactorを使ってReactive Streamsで書いています。
Coroutinesはいいのですが、私たちのシステムはキューを使ってたくさんのオペレーションをフィルターしたりflatMapしたり、さらにもっと大きな非同期オペレーションを高速で呼んだりというのを繰り返すので、どうしてもCoroutinesのAsynchronous Flowみたいな機能が必要になってきます。
ReactorもRxJavaも使ったことがありますが、それに比べるとCoroutinesのFlowのOperatorが貧弱かなと思っています。そういう処理をするとどうしても冗長になってしまったり、きれいに書けないことがあったりして、やはりこういう処理にはReactorのほうが向いているのかなと思っています。
また、ReactorはSpringのサポートも手厚いので、Reactive Streamsの学習コストさえ乗り越えられるのであれば、Coroutinesを無理やり使わなくてもいいのかなと思うところがあり、Reactorを採用しています。
Messaging APIの中でKotlinを使ってみての書き心地ですが、Javaを使っているとほぼ困るところがないのがいいところかなと思っています。Nullableやsmart castなど便利な機能が取り入れられているので、かゆいところに手が届きます。
また、Scalaよりもはるかに良いJavaとの親和性があります。拡張関数など、今まではきれいに書けなかったコードもきれいに書けるようになるのがKotlinのいいところです。
ただ、チームの中にはScala派閥の方もいます(笑)。そういう方からすると、やはりKotlinでも機能が足りず、パターンマッチングが弱いだとか、Scalaのforみたいなフラットマップが言語としてサポートしてほしいだとか、そういう意見がよく出てきます。
また、最近KotlinのExperimentalな機能はけっこう変わっていて、実験的に全部書き直さなければいけません。特にExperimental timeあたりのメソッドがdeprecatedになっていたりしてすごく気になります。
Javaから移行するとどうしてもコンパイルに時間がかかったり、IDEもちょっと重いのが気になる点かなと思いますが、これ以上にKotlinのメリットは多いと今のところ私は思っています。
(次回へつづく)
LINE株式会社
関連タグ:
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
職場であえて「不機嫌」を出したほうがいいタイプ NOと言えない人のための人間関係をラクにするヒント
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.06
嫌いな相手の行動が気になって仕方ない… 臨床心理士が教える、人間関係のストレスを軽くする知恵
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
2024.12.11
大企業への転職前に感じた、「なんか違うかも」の違和感の正体 「親が喜ぶ」「モテそう」ではない、自分の判断基準を持つカギ
PR | 2024.11.22
「闇雲なAI導入」から脱却せよ Zoom・パーソル・THE GUILD幹部が語る、従業員と顧客体験を高めるAI戦略の要諦