本日2015年6月30日、LINE Login PlatformをLINEではない他のサービスでも利用できるように公開しました。 今回の記事では、公開されたLINE Login Platformについて紹介しようと思います。 技術的な内容が掲載されているLINE developersサイトも公開いたしましたので、どのような機能を利用することができるのか、ぜひご覧になってください。 LINE Login Platformとは? LINE Login Platformとは、皆さんが開発したスマートフォンアプリやウェブアプリケーションの中で、LINEアカウントを使用したログイン機能を組み込むためのプラットフォームです。 すでに多くのスマートフォンアプリやウェブアプリケーションが、LINE Login Platformを使ってログイン機能を利用しています。ここでは、例としてPopcorn BuzzとLINE STOREそれぞれでどのようにログイン機能が利用されているのか紹介してみます。 Popcorn Buzz: スマートフォンアプリの場合 Popcorn Buzzは、同時に最大200人と無料で通話をすることができるAndroid/iOS向けのスマートフォンアプリです。Popcorn Buzzのようなスマートフォンアプリでログイン機能を組み込んだ場合は、以下の画面のようになるでしょう。Popcorn Buzzの画面に”Log in with LINE”というボタンを配置して、ユーザがそのボタンをタップした際に、LINE Login Platformのログイン機能を呼び出すように組み込んでおきます。そのユーザの端末にLINEアプリがインストールされていれば、2つ目の画面にある同意ボタンをタップするだけで、ログインが完了します。LINE Login Platformは多くのスマートフォンアプリにユーザ体験の良いログイン機能をもたらしてくれます。 LINE STORE: ウェブアプリケーションの場合 LINE STOREは、スタンプや着せ替えを販売しているウェブアプリケーションです。PCやスマートフォンのウェブブラウザから利用することが可能です。LINE STOREのようなウェブアプリケーションでLINE Login Platformのログイン機能を組み込んだ場合は、ユーザが予めLINEアプリ内で登録しておいたメールアドレスとパスワードを入力する画面が表示されます。更に先ほどのスマートフォンでの例のような同意画面でユーザが同意ボタンを押下することで、ログインが完了します。スマートフォンアプリと同様に、ウェブアプリケーション側で独自にアカウントを発行する仕組みを開発する必要なく、LINEを使っているユーザでログイン機能を組み込むことが可能です。 ログインしたユーザーの情報 LINE Loginを使ってサービスにログインした場合、サービスはユーザーの同意のもとで、下記の基本的なユーザー情報を連携することができます。 LINEで設定された名前 LINEで設定されたプロフィール画像 LINEで設定されたひとこと LINE上の内部的な識別子 LINEの友だちの一覧、グループ情報など、上記以外のユーザー情報は連携されません。 LINE Login Platformがもたらすもの 便利さ LINEユーザなら簡単にサービスにログインできるため、ユーザの立場から見てサービスのユーザビリティがとても高くなります。 ユーザの増加と利用の活性化 LINEは全世界で5億人以上のユーザが使っているメッセンジャーサービスです。LINE Login Platformを組み込んだサービスでLINEユーザが手軽にログインすることができれば、結果的にそのサービスの利用者数が増加することに繋がり、さらにそのサービスの活性化や売上の増加を期待することができます。 様々なプラットフォームのサポート LINE Login Platformは、iOSアプリ、Androidアプリ、そしてウェブアプリケーションに対応しています。 iOSとAndroidに関しては、LINE Login Platformをより簡単に組み込むために、SDKを提供しています。 実績が豊富なプラットフォーム LINE Login Platformは、すでにLINEが提供している多くのサービスで利用されている実績の多いプラットフォームです。 LINE Login Platformを利用するには? LINE developersサイトについて LINE developersサイト(https://developers.line.me)は、LINE Login Platformを含むLINE Platform全体の技術的な内容が掲載されています。このサイトに訪れることで、LINE Platformが提供している様々な機能を知ることができるでしょう。そして、実際にLINE Login Platformを利用するために必要となる各種登録作業や設定作業を行うための管理画面もここで提供しています。LINE Platformに連動するスマートフォンアプリやウェブアプリケーションを開発する際には、最初にPartner登録、そしてChannel登録を申請します。その後承認された後に、右上のChannelsタブから管理画面に進むことができるようになります。 Partner登録 最初にやるべきことは、Partner登録です。 本記事の公開時点では、LINE Login Platformの利用を希望する法人のみ申請を受け付けています。 LINE Partnerの登録は、LINE developers サイトのPartner登録フォームから行ってください。 このフォームでは、会社情報、担当者のメールアドレス、連絡先、LINE Login Platformを利用したいスマートフォンアプリやウェブアプリケーションに関する簡単な説明を入力することになります。フォームから情報を入力後、登録完了およびメールアドレスの存在確認のためのメールが自動的に登録者に送られます。登録された内容は、LINE社の担当スタッフによって確認、検討が行われます。後日LINE Login Platformの利用可否1の検討結果が再度メールにて送られることになります。多くの企業から申請があった場合は、結果が送られてくるまでに時間かかることがありますので、予めご了承ください。 LINE Login Platformの利用が承認された後、LINE developersサイトにログインすることができるアカウントが発行され、結果通知のメールにてそれをお伝えいたします。パスワード変更後に、いよいよ管理画面に入ることができるようになります。 1: 利用可否基準については、Partner登録フォームページ下部の「Please note」部分をご参照ください。 Channel登録 管理画面に入ることができた後は、実際にLINE Login Platformの機能を利用するために、”Channel”登録を行います。私達は、LINE Login Platformの機能を利用することでLINEと連携されたスマートフォンアプリやウェブアプリケーションのことを、総称として”Channel”と呼んでいます。Channel登録の手順は、下記のような流れです。 (…)
↧
LINE Login Platformを公開いたしました
↧
LINE Bug Bountyを公開いたしました
こんにちは。LINEでセキュリティを担当しているMJです。今回の記事では、LINEのBug Bountyプログラムについてご紹介させていただきます。 Bug Bountyとは Bug Bountyとは、自社の製品やサービスのキュリティ上の脆弱性を発見した人に報奨金を支払うプログラムで、グローバル企業では製品・サービスのセキュリティ強化策として積極的に取り入れられています。実際、多数の企業がこのプログラムを活用して自社のサービスの品質改善とセキュリティ向上を図り、セキュリティ問題を解決しています。 LINEは、毎月の実ユーザー数が2億人以上に達するグローバル企業に成長しました。この成長過程で、数多くのアプリケーションと増えたユーザーをセキュリティーの脅威から保護することが求められるようになりました。そのため、LINEはBug Bountyプログラムを実施することで、より安心・安全なサービスの提供を目指してまいります。 Bug Bountyプログラムの最大の目標は、自社の製品・サービスの脆弱性をできるだけ早期に見つけて安心できるサービスを提供し、ユーザーを保護することにあります。ハッキング技術は日々進歩しており、ゼロデイ攻撃(Zero day attack)が頻発しています。しかもそのような攻撃が個人レベルではなく組織的に行われるという現在のインターネットの状況を見ると、どの企業でもセキュリティ面で100%の安全性を保証するのは難しいでしょう。なお、IT技術は目まぐるしい速度で発展し続けているため、攻撃者の観点から考えないとセキュリティの脅威を防ぎにくいのが現状です。これを受け、LINEでもBug Bountyプログラムを導入して世界中のホワイトハッカーの皆様より脆弱性の報告を受け付け、セキュリティ問題の改善に向けて積極的に取り組んでいます。 他社のBug Bounty これまでLINEは、社内専従セキュリティチームによる脆弱性分析のほかにも、日本とタイのCERT部門からフィードバックを受けて共同で対応し、不具合を改善してきました。こうした取り組みに加え、さらに積極的に脆弱性を探すためにBug Bountyプログラムを導入することを決めました。 GoogleやFacebook、Microsoftのようなグローバル企業の場合、自社の製品およびサービスのセキュリティ強化策としてBug Bountyプログラムを積極的に活用しています。 【表1. 各企業におけるBug Bountyの運営状況】 企業名 Bug Bountyプログラムの運営状況 Google 2010年に脆弱性のリワードプログラムをスタート。脆弱性の種類によって100ドルから20,000ドルまでの報酬を提供。 Facebook 2011年より運営。報奨額は最低500ドル、上限はなし。 Microsoft 2013年より多彩なプログラムを展開。同年11月にFacebookと共同で立ち上げた「Internet Bug Bounty Program」では最低5000ドルの報奨金を提示。 サービスのグローバル展開を行う海外企業の間では、サービスの不具合を改善でき、ハッキングによる事故を予防できるBug Bountyプログラムは当たり前と言えるほど、同プログラムを運営する企業は多数に上ります。以下のURLにて、Bug Bountyプログラムを提供している企業のリストをご確認できます。 Bug Bountyプログラムがある企業 なお、企業がプログラムの運営に直接関わらず、会員制Bug Bountyプログラムを運営する会社を通じて同プログラムを提供している場合もあります。代表的な運営会社としては「HackerOne」があり、多くの企業が利用しています。 最近、マイクロソフト社が新OSのWindows 10とともにリリースされるウェブブラウザ「Microsoft Edge(コード名:Spartan)」に対するBug Bountyプログラムを運営し、話題になりました。上海で開催された「Mobile Security Conference(MOSEC) 2015」では、同社のBug Bountyプログラムについての紹介がありました。 (上記の写真は、筆者がMOSEC 2015の会場で撮影したものです) マイクロソフト社は、多数の製品とサービスを提供しているだけに、各製品・サービスに特化した様々な形のBug Bountyプログラムを運営していました。なお、毎年数百人以上のホワイトハッカーから脆弱性の報告を受け取っていました。ホワイトハッカーは一部の地域に集中しているわけではなく、アジア、ヨーロッパ、北米・南米大陸など世界各地に広がっています。同社は、脆弱性の報告者が自社の製品・サービスの安全性向上に非常に大きな役割を果たしていることから、彼らとの関係を保つために絶え間なく努力していました。 このように海外ではBug Bountyが活発に行われているのに対し、日本と韓国においては一部の企業だけがBug Bountyプログラムを運営しています。 LINE Bug Bounty Program LINEは、2015年8月半ばから1ヶ月間、「LINE Bug Bounty Program(脆弱性報奨金制度)」を展開します。コミュニケーションアプリ「LINE」の脆弱性を発見し、ご報告いただいた方には、謝礼として報奨金をお支払いいたします。報奨額はご報告の内容によって異なり、1件あたり最低500米ドルから20,000米ドルまでです。 実施期間 LINE Bug Bounty Programは、以下の期間実施されます。 2015年 8月 24日(GMT+9) 午後12時 ~ 9月 23日(GMT+9) 午後12時 報奨金 LINEの脆弱性を発見し、ご報告いただいた方には、下表のとおり報奨金をお支払いいたします。 【表2. 脆弱性の種類による最低報奨金額】 脆弱性名 説明 最低金額 message / call eavesdropping 他人のメッセージ、通話を盗聴、解読、改変、及び終了可能 USD 10,000 SQL Injection SQLインジェクションにより、個人情報閲覧が可能 USD 3,000 Cross-Site Scripting(XSS) XSSにより、sessionhijackやスクリプト実行が可能 USD 500 Cross-Site Request Forgery(CSRF) CSRFにより、LINE利用者が意図しない処理をさせることが可能 USD 500 Client-Side Remote Code (…)
↧
↧
True Delete機能のご紹介
こんにちは。LINEでアプリケーションのセキュリティを担当しているH2spiceです。今回の記事では、スマートフォンを紛失したときにユーザーが削除したトーク履歴が流出する仕組み、そしてそれを防止するためのLINEの新機能「True Delete」についてご紹介します。 はじめに 多くの人はスマートフォンを紛失したり、時には人通りの多い公共の場所にスマートフォンを放置したりします。もし紛失したスマートフォンを他人が拾った場合、スマートフォンに保存されているデータにアクセスして流出することができるので、かなり深刻な問題が起こる可能性があります。スマートフォンには通話履歴、メッセージ、電話帳、カレンダー、インターネット検索履歴、移動履歴、写真、メモなどたくさんの個人情報が詰まっているので、プライバシーの漏洩はもちろん、会社の業務上の機密が外部に流出する問題も発生しかねません。さらに、そのような情報を狙ってスマートフォンを盗む場合もあります。スマートフォンは便利な道具ですが、管理の不注意やちょっとした油断によって個人のプライバシーの侵害につながる危険な道具にもなり得ます。 LINEでは、このようなリスクからユーザーのプライバシーを保護するために、パスコードロックやデータの暗号化のような機能を追加するなど、さまざまな努力をしています。しかし、いくつかの問題のため、一部のリスクは依然として存在しています。「削除」という一般的なプログラム手法上の限界によって、削除されたデータを復元できてしまうことも問題の一つです。では、一般的な削除方法における問題点とそれを補うためにLINEが開発した「True Delete」機能をご紹介します。 メッセージ削除の限界 人々とのコミュニケーションのためにLINEのようなメッセンジャーアプリを毎日使う人が増えています。友達との日常的な会話のやりとりがほとんどですが、たまに家族にクレジットカード情報とパスワードを送ることもありますし、友達に自宅の住所を教えることもあります。万が一スマートフォンを紛失したときに備えて、そのような機密なメッセージをいちいち削除している人もいるでしょう。そうすれば自分のスマートフォンからそのメッセージが完全に消えたと思うはずです。 スマートフォンをいつも身から離さなければ問題ありませんが、ジムの更衣室や外のトイレなどでスマートフォンを紛失、または盗まれる場合を想定すれば、それはまた別の話です。まるで映画のようなことが起こるかも知れません。機密なメッセージを確かに消したつもりだったのに、誰かがその内容を見ることができる、知らないうちにクレジットカードが使われる、自分の秘密がインターネット上に出回るということは、想像するだけでもぞっとします。 一部のアプリケーションで採用されている一般的な削除方法で消されたデータはいくらでも復元できるので、個人情報の漏洩は現実でも起こり得ます。Avast社は昨年、eBayで購入した中古スマートフォン20台から削除されたデータを復元することに成功しましたが、その復元した4万枚の写真のうち750枚以上がヌード写真だったそうです。このような研究結果を見ると、プライバシー漏洩は決して他人事ではありません。 では、削除したデータがどのように復元されるのか、メッセージ削除の限界についてもっと詳しく見ていきましょう。お使いのパソコン・スマートフォンの削除機能のほとんどは、性能上の問題や実装の利便性のため、実際にはデータを削除しません。ただ、削除されているように表示し、その領域を後で再利用可能な領域として扱うように変更するだけです。そのため、新しいデータで上書きする前までは、以前のデータがそのまま残ってしまいます。このような仕組みのため、削除されたデータの復元が可能になるわけです。 一般的な削除の仕組み 一般的な削除の仕組みは、下図のとおりです。データが格納されるファイルシステムにおいて、データの先頭にはそのデータの属性情報(メタデータ)が定義されています。データが削除されれば、属性情報(メタデータ)のステータスは「割り当て済みデータ(Allocated Data)」から「未割り当てデータ(Unallocated Data)」へと変わり、データ本体はそのまま残存します。未割り当てデータの領域が新しいデータで上書きされる前までは、復元できる状態のまま残っています。 AndroidとiPhoneのOSでは、メッセージや通話履歴など多種多様なデータをすべてSQLiteというデータベースに保存します。データベースでも上述したやり方でデータ(レコード)を削除しますが、結果的には削除されたデータ(レコード)は復元できる状態で残されます。データベースで削除されたデータ(レコード)は、データベース内にそのデータのかけらが残るので、削除されたファイルよりもっと簡単に復元できます。SQLiteデータベース自体が削除されない限り、削除されたレコードは新しいレコードで上書きする前までは未割り当て領域(Unallocated space)に残っています。 削除されていないデータのデータベース構造 削除されていないデータは、データベース内に以下のような構造で存在します。データーベースにおいてアクティブになっているデータを「Cell」といいますが、アクティブのCellは、下図のような構造を持っています。 一般的なCell Cellは大きくCell Header、Data Header、Data Areaに分けられ、Cell Header内のレコードサイズとRowIDは可変長整数で表現されています。Data Headerには、Data Areaのデータがどんなタイプのものなのかが示されており、Data Areaにはデータ本体が格納されています。ユーザーのメッセージは、LINEアプリ内のデータベースに下図のように保存されます。 上図のデータベースのバイナリーを分析してみると、Cell HeaderやData Header、Data Areaを確認できます。削除されていないデータなので、割り当て済み(Allocated)状態のCell Headerとデータ本体を見ることができます。 削除されたデータのデータベース構造 データベース内のデータ(レコード)を一般的な方法で削除すると、下図のようにデータ本体はそのまま残り、Cell Headerの部分のみ変更されます。削除されたデータの場合、Cell Headerは未割り当て(Unallocated)状態になっています。その後新しいデータ(レコード)を保存するときには、未割り当て(Unallocated)領域をチェックし、適正なサイズの未割り当て(Unallocated)領域に新しいデータ(レコード)が上書きされます。 削除されたCell ユーザーのメッセージである「hi」、「h e l l o(UTF-8)」、「h i(UTF-8)」を削除した後、SQLiteブラウザからデータベースを確認してみると、「hi」、「h e l l o(UTF-8)」、「h i(UTF-8)」のデータは削除されているように見えます。 しかし、データベースのバイナリーを確認してみると、Cell Headerが未割り当て(Unallocated)状態に変わっただけで、データ本体はそのまま残っていることが分かります。 このような仕組みによって削除されたデータ(レコード)を復元でき、自動化プログラムを作成して削除されたデータを抽出することができます。 データの完全消去 上述の一般的なデータ削除方法では、新しいデータで上書きする前までは既存のデータをほとんど復元することができます。このようなデータ復元を不可能にする手法を「完全消去」といいます。完全消去のやり方としては、以下のような方法があります。 データの上書き(Overwriting) 削除したいデータをゼロbyteまたはランダムbyteで上書きします。上書きされたデータは復元がとても難しくなります。 暗号化(Encryption) 安全な暗号化方式を使用してディスクまたはファイルを暗号化し、データが復元・漏洩されたとしても中身が分からないようにします。 消磁(Degaussing) HDD(Hard Disk Drive)は磁性体を使ってデータを記録しますが、強い磁場にさらしてディスク表面の磁気の流れを完全に破壊し、データを使用できないように削除します。 磁気力顕微鏡でディスク表面の形状を測定できますが、消磁した後は下図のようにディスク表面のデータ形状が破壊されていることが分かります。 物理的破壊・穿孔・破砕(Physical Destruction) 物理的に穴を開けるか破砕することでディスクを完全に破壊します。通常、消磁した後にディスクを完全に破棄するために使います 安全なメッセージ削除「True Delete」 LINE 5.3.0からは、上述の方法でデータの復元を不可能にする「True Delete」という機能が採用されました。ユーザーのプライバシーは常に保護されるべきなので、「True Delete」機能は別途設定しなくても使用できます。 一般的な削除は、データの属性情報(メタデータ)が変更されるだけでデータ本体はそのまま残ります。このような方法ではデータの復元が可能なので、削除したいデータをゼロbyteで上書きしてから削除することで復元を不可能にします※注。LINE 5.3.0では、個別メッセージの選択削除、当該トークルームの削除など、すべてのトーク履歴削除機能については復元ができないように機能を改善しました。任意の削除ではなく、復元が不可能な「削除」の機能を正しく実装したと言えます。 ※注: 「True Delete」は、SQLiteとの互換性を持って機能するように実装されました。そのため、削除直後のほんの短い間は以前のデータが残っている可能性はありますが、正常な使用シーンでは安全に削除されるので、ご心配には及びません。 おわりに LINEは、ユーザーのプライバシーを保護するためにパスコードロック、Letter Sealingなど様々なプライバシーモードの開発に努力を傾注しています。LINE 5.3.0からは、さらに強化された暗号化方式のE2EE(end-to-end encryption)として「Letter Sealing」機能をご利用いただけます。次回の記事では、「Letter Sealing」について詳しくご紹介します。 今後もユーザーの皆様に安心してLINEを楽しんでいただけるよう、セキュリティとプライバシーの向上に一層取り組んでまいります。
↧
メッセージの安全性新時代:Letter Sealing
こんにちは。LINEでセキュリティに関する調査、開発を担当しているJIです。 今回の記事では、メッセンジャーアプリにおけるセキュリティについて、中でもネットワークを通じたメッセージの送受信時に想定される問題と、その解決のためにLINE 5.3より追加されたLetter Sealing機能についてご紹介します。 メッセージを安全に渡す方法 秘密情報のやり取りは太古の昔からずっと行われてきたことであり、人々は人通りの少ない場所に隠れて密かに内緒話をしたり、仲間内だけで通じる暗号を使って他人には解読不能にしたりすることで、秘密が漏れないようにしてきました。 しかし、このような方法は相手が近い距離にいる場合に限って使えるものでした。インターネットのような遠距離通信手段が存在しなかった頃は、文字を書いた文書を封筒に入れ、受取人へ人づてに渡す方法しかありませんでした。ただし、人が配達する過程でも、封筒をこっそり開封して中身を盗み見てから元通りに封をしてそのまま届けるという問題が発生しました。また、文書の内容を修正・改ざんして違う内容のものを渡されていたとしても、それを差出人が確認できる方法はありませんでした。そのため、差出人が書いた内容を配達員から安全に守りながら伝達することはとても難しいことでした。 そこで、人々は新しい方法を思いつきました。内容の秘密保持ができないならば、少なくとも誰が文書を作成したのか、誰かが途中で封筒を開封していないか確認できる印をつけるべきだと思うようになったのです。こうして誕生したのがシーリングスタンプ(letter seal)です。これは、伝えたい内容を書いた文書にしっかり封をした後、蜜蝋(wax)のようなもので完全に封印する方法でした。配達員が中身を見るには封蝋を破らなければならないため、受取人は封の状態を見て配達中の盗み見や内容の改ざんの有無を確認することができました。そして、破いた封を元に戻せなくするために、固有の文様が刻印された印璽(シール)を押しました。 このように昔から使われてきた封印の仕組み(封蝋)は、配達中に発生し得る様々なリスクから文書を守る役割を果たしました。しかし、これは紙の文書でやり取りしていた時代に有効だった方法です。現代のようにインターネットを介して情報をやり取りするとき、中でもLINEでメッセージを送るときには、どのような方法でメッセージの安全性を保証しているのでしょうか。その方法について詳しく見てみましょう。 LINEが提供する基本的な暗号化方式 モバイル時代の現在、すべてのメッセンジャーサービスやSNSにはメッセージを送受信・保存するためのサーバがあります。サーバは、ユーザーから送られてきたメッセージやその他の情報を受信者に転送する役割をします。受信者にすぐ送れない場合は、サーバはそのメッセージを一定期間保存し、ユーザー宛に新規メッセージが届いたことをプッシュ通知(push notification)でお知らせします。 メッセンジャーサービスにおいては、サーバに送られてくるメッセージの安全性を保証するための暗号化が非常に重要な技術となります。LINEでも、サーバに送られてくるユーザーの様々な情報に対して、第三者による不正アクセスを遮断するため、メッセージの暗号化を実施しています。ユーザー端末のメッセンジャーとサーバとの間の暗号化通信の流れを簡単に図で表すと、下図のようになります。 LINEでは、ユーザー端末(Sender)とサーバ(Server)間の通信を公開鍵暗号(public key encryption)方式を使って暗号化しています。ユーザーに対してLINEアプリを提供する際、暗号化ができる公開鍵のみをアプリに入れて提供し、ユーザー端末とサーバが接続されたときだけLINEサーバでのみ解読できる暗号化された安全なチャネルを作ります。このとき通信内容は暗号化されますが、サーバ内では一度復号された後、再度暗号化するため、(サーバ内では)一度平文に戻されることになります。 現在LINEではRSAという公開鍵暗号化方式を使用しています。LINEでのRSAの使い方を少し詳しく説明しましょう。 ユーザー側のLINEアプリ(クライアント)には、サーバが発行したRSA鍵を使用してデータの暗号化に使う暗号化鍵値を共有します。この鍵を利用してデータを暗号化すると、第三者はメッセージを見ることができなくなります。この方式が安全だといえるのは、RSAの秘密鍵がLINEサーバでのみ保管される値であるためです。なので、LINEサーバがハッキングされて鍵が盗まれることや、管理者が万が一にも誤って鍵を漏洩させてしまうといった事態に対しては、依然リスクが残ってしまいます。 そのため、この方式においては、サーバに保管されている暗号化鍵を安全に管理することが最も重要です。その一方で、インターネットサービスが日常生活に浸透している現在において、悪意を持った攻撃者の手法も日々変化し、その攻撃による一般ユーザーへの影響も拡大しています。なお、コンピューター技術の高度化に伴いハッキング技術も進化し、これまで経験しなかった様々な形のハッキング事件が発生しています。さらに、個人中心だった攻撃者の活動が集団化・組織化して攻撃の規模も大きくなり、相対的に安全だとされていたサーバへの攻撃事例も発生し始めています。そのため、より安全にサービスをお使いいただけるよう、リスクの再評価と対策が求められるようになりました。 このような流れもあり、LINEは発生し得る様々なセキュリティリスクの再評価を継続的に行い、メッセージ保護方式のさらなる強化を検討していました。その強化策の一つとして、昔使われていた封蝋を現代のデジタルメッセージの送受信にも導入することを考えました。つまり、LINEのサーバで大量生産された既存の封蝋を使うのではなく、各ユーザーが固有の封蝋を直接作って使うようにし、メッセージの安全性の強化を図りました。そして、このLINEの新しいメッセージ保護機能には「Letter Sealing」という名前をつけました。 Letter Sealing: 改善点 Letter Sealingという新機能は、果たして何を強化したものなのでしょうか。 まず、技術的に安全なアルゴリズムを使用して、送信者と受信者が安全な暗号化鍵を交換できるようにしました。Letter Sealingでは、既存のRSA方式による鍵交換ではなく、Diffie-Hellman(以下、DHという)方式で暗号化鍵を交換します。これは、暗号化鍵を暗号化して転送する方式ではなく、両者がお互い公開してもいい値を共有するだけで第三者には分からない値をオフラインで生成できる方式です。 メッセージを交換したい両者はDHの公開鍵と秘密鍵を用意し、LINEサーバを介して公開鍵のみを相手に渡すことで、メッセージを中継するLINEサーバにも分からない暗号鍵を生成することが可能になります。秘密鍵はクライアントにのみ保存され、LINEサーバに送られることはありません。 DHについてもう少し詳しく説明しましょう。DHには、離散対数と楕円曲線計算の2種類の数学的技術を使った実装方法があります。Letter Sealingでは強力なセキュリティ方式として評価されている楕円曲線DH方式であるECDH(Elliptic Curve Diffie-Hellman)を使用しています。楕円曲線DHは、離散対数方式と既存のRSA方式に比べて小さいデータ量で高い暗号化強度を実現できます。Letter Sealingは、ECDHの導入によって暗号化強度が向上するだけでなく、データ量が小さいので鍵管理の効率性も高まるという、2つのメリットを享受することができます。 DHにより送信者と受信者の双方が共有する鍵(共通鍵)を得た後は、AES-CBC-256アルゴリズムで暗号通信を行います。この暗号化方式を使用する上で重要なことは、暗号化の対象と暗号を解読する復号化の対象がすべて同じ鍵データを持たないといけないことです。ここで使用する値が上述のDH鍵共有方式によって得られた暗号鍵です。 このような方法で両者が得た共通の値、shared secretを共有した後は、メッセージデータを暗号化します。LINEの場合、先ほど説明したECDH方式で256Bits(32Bytes)の共有値を生成し、これを通じて暗号化に使う鍵値を作成します。その後、暗号化されたメッセージとそのときに使用した鍵データに関する情報を一緒に送ります。しかし、メッセージを単純に暗号化して送るだけでは十分なセキュリティ対策になりません。実際、インターネット上には、間に割り込んでメッセージの内容を読めなくしたり、改ざんしたりすることで送信を妨げる攻撃が存在します。 このような攻撃を防ぐため、Letter Sealingではメッセージ認証コード(Message Authentication Code、以下MACという)という機能を追加しました。これは、メッセージが送信される前の元のメッセージを暗号学的に要約しておき、後で受信者がこのMAC値と実際のメッセージの値を比較して一致しなければ、改ざんされたことを検知できる機能です。この方式を活用すれば、第三者によるメッセージの改ざんを受信者側で検知することができます。なお、MACは共有データを持っている送信者と受信者しか作成できないので、メッセージが手つかずであることを保証できます。 このような技術を基に、Letter Sealingは機能的にも既存の方式と差別化を図ることができました。代表的な差別化ポイントとして挙げられるのは、Letter Sealingでは、メッセージの暗号化などの管理主体がサーバからメッセージ送信者(sender)に変わったという点です。これにより、かつてサーバ上で行っていた復号、および再暗号化が不要、また技術的に不可能になりました。これにより、他ユーザーはもちろん、LINEサーバの管理者でさえ、メッセージの内容を解読(復号)することはできなくなりました。 以上より、新しい暗号化方式を使用すれば、メッセージ転送において、一度も平文に戻すことなく安全にデータを宛先へ送り届けられます。かつて文書を届ける際に封蝋で閉じて盗み見や改ざんを防いだように、この新しいメッセージ保護方式ではメッセージをデジタル封蝋して受信者に届くまで保護します。 Letter Sealingの使い方 ご紹介したLetter Sealingをはじめ、同時に追加されたセキュリティ機能は、通常の新規サービスとは異なり、一見既存の機能と大差が無いように感じられるかもしれません。確かに地味で実感されにくい機能なのですが※注1、この機能はLINEのセキュリティを確実に高めるものです※注2。 なお、Letter Sealing機能を使用するには、以下のように設定する必要があります。 LINE 5.3.0以降のバージョンをお使いの方は、その他 > 設定 > トーク・通話にてLetter Sealingのオプションをご確認いただけます。LINEのiOS版・Android版でこのオプションをオンにするだけで、Letter Sealing機能が使えるようになります。 なお、本機能を段階的に適用拡大すべく、まずはAndroidユーザーのうちWindows、Metro、Mac、iPad、Chrome版LINEを使ったことのない一部の国のユーザーを対象に、9月よりLetter Sealing機能をデフォルト有効状態にして適用しています。Letter Sealing機能をオプションでオンに設定している、またはデフォルトで有効になっているAndroidユーザーであれば、1:1トークでテキストメッセージと位置情報をやり取りする際にLetter Sealing機能のメリットを享受することができます。ただし、この機能はオンに設定したユーザー同士でのみ使えるようになっています。そのため、この機能を活用したい方は、一緒にトークしたい友だちにもこの新機能を紹介して使用できるようにしてください。 今後、LINEでは、さらなるセキュリティ向上のため、他の形態のメッセージやグループトークなどにも適用する予定ですので、これからもLINEとサービスのセキュリティに一層のご支援ご指導のほどよろしくお願いいたします。 ※注1: 現在のバージョンのLINEでは、会話中のトークルームがLetter Sealingモードであるかどうかは表示されません。今後のバージョンに適切な表示を追加することを検討しています。 ※注2: 現時点では、Letter Sealingはテキストメッセージと位置情報に対してのみ適用されます。
↧
LINE Bug Bountyの結果と総括
はじめに こんにちは。LINEでセキュリティに関する業務を担当しているMJです。以前こちらの記事で、LINE初の試みである「LINE Bug Bounty Program」について紹介いたしましたが、今回、改めて内容を振り返りながら、その結果について書かせていただこうと思います。 LINE Bug Bountyは、8月24日から9月23日までの約1ヶ月間で行われ、その期間に発見した脆弱性を報告してくださった方には、最高で1件20,000米ドル(約240万円)をお支払いするというプログラムです。このような制度は国内ではまだ実施例が少なく、あまり馴染みがないかもしれません。しかし、LINEではユーザーの皆様により安全なサービスを提供したいと考えており、そのための取り組み、制度のひとつとして、今回のBug Bounty Programを実施しました。 本プログラムは我々にとっても初めての試みでありまったくの未知数だったのですが、結果的に194件の報告を受け、XSS、CSRFなど計14件をクリティカルな脆弱性として対応させていただきました。また報告件数の半分以上は日本国外からのものであり、海外のユーザーからの関心も大きかったことは大きな驚きでした。 では、結果の詳細について実際に見ていきましょう。 受付状況 まず、報告フォームでの受付件数【図1】を見てみましょう。 日付別の受付状況 8月24日から9月23日までの約1ヶ月間の総受付件数は、194件に達しました。受付開始初日の応募が最も多かったのですが、これはLINE Bug Bounty ProgramのWebサイトを8月5日にオープンし、対象サービスとドメインを先に公開したためだと思われます。事前に発見していた脆弱性を受付開始と同時に報告してくれたのでしょう。その後は、時間が経つにつれ受付件数が徐々に減少していき、受付締切日が近づくと再びやや増加していく傾向が見られました。 国別のアクセス比率 次に国別のアクセス比率を見てみましょう。 【図2】は、実施期間中におけるLINE Bug Bounty ProgramのWebサイトへのアクセス比率を国別に示したものです。国別の受付件数をみると、日本からは89件、日本以外の国からは105件となっており、日本だけでなく、様々な国から高い関心を受けていたことが分かります。また今回の報告者のうち、10名の方が5件以上の報告をしてくださり、中には1人で16件もの報告をしてくださった方もいました。 審査および結果 審査過程 ご報告いただいた内容に対しては、1次審査と2次審査の2段階に分けて審査が行われました。 まず1次審査では、報告の内容がセキュリティの脆弱性に関するものか、十分な説明があるか、日本語または英語で作成されているかなどを審査しました。例えば、「LINEアプリをアップデートしたら起動しなくなった」などの内容は、脆弱性に関するものではありません。また、証拠の画面のみご報告いただいた件は、十分な説明がないことから1次審査の対象外となりました。 続いて2次審査では、1次審査を通った内容が脆弱性に値するかどうかを審査しました。利用規約上のサービス・ドメインを対象にしているか、エクスプロイトコード(exploit code)が実際に再現されるかなどの事実確認を行い、脆弱性と判断できるかをチェックするのが審査の主な内容です。 審査は、5人の審査委員によって行われました。審査委員は各部門のセキュリティエンジニアで構成されており、他社のBug Bountyに参加した経験のある人も含まれています。2次審査委員は、報告の内容を確認し、今回のBug Bountyの認定条件を満たしているかを踏み込んで検討しました。 2次審査を通過したものは脆弱性として認定され、報奨金が支払われました。そして、Hall of fame(名誉の殿堂)において報告者のお名前や脆弱性の種類などを公表しました。 審査結果 今回のプログラムでは、XSS、CSRFなど計14件が脆弱性として認められました。また、ご報告いただいた内容が本プログラムの利用規約上の対象範囲外ではあったものの、LINEのための有益な情報を報告していただいた10名の方を「Special Contributors」として選定し、報奨金をお支払いしました。 審査結果の詳細については、Webサイト(Hall of fame)をご覧ください。 参加者インタビュー 最後に、Bug Bounty Programの参加者の方にその感想をお聞きしましたので、ご紹介させていただこうと思います。 Q: ご参加のきっかけは何ですか。 A: 普段から、モバイル環境でいろいろなアプリの脆弱性を見つけることが趣味でしたが、ちょうどLINEがBug Bounty Programを実施すると聞き、参加しようと思いました。メッセンジャーアプリのBug Bounty Programは珍しいので、いい機会だと感じました。 Q: 脆弱性を発見できた経緯を簡単に教えてください。また、アプリを分析していて大変だったことは何ですか。 A: とにかくソースコードがない状態でアプリを分析しないといけなかったので、いろいろと分析方法を工夫する必要がありました。LINEは特に、他社のアプリよりデバッグが難しかったですね。 Q: Bug Bounty Programに参加して感じたことはありますか。 A: メッセンジャーアプリなので、これまであまり知られていなかった攻撃経路(attack vector)とバグを見つけ、エクスプロイト(exploit)まで作成するのが楽しかったです。自分で作った攻撃コードが実際に動作するのを見て、やりがいを感じました。他社の場合は、脆弱性を見つけて報告すると、感謝の言葉ではなくネガティブな反応が返ってきて、パッチに長い時間がかかることがありました。それに対しLINEは、Bug Bounty Programを運営すること自体、セキュリティ強化への関心と意欲を表しているのだと思います。また、脆弱性として認定されるために必要なことについて、スタッフの方が親切に教えてくれたこともよかったです。 Q: Bug Bounty Programに参加して残念だったことはありますか。 A: 特に残念だったことはありません。今回はプログラムの対象がメッセンジャーアプリに限られていたので、今後は対象範囲をWebにも拡大してほしいです。 今後のBug Bountyについて 約1ヶ月間の短い期間でしたが、多くの皆様のご関心・ご参加に支えられ、今回のBug Bounty Programを無事に終了することができました。また、本プログラムはLINEとして初の試みでしたが、様々な脆弱性を発見することができた事の効果を、大変に実感しております。今回ご協力をいただいた全ての皆様へ、関係者一同こころより御礼を申し上げます。尚、今回認定された脆弱性は、最新バージョンのLINEにて修正が完了しています。最新バージョンにアップデートしていただくことで、より安全にLINEをご利用いただくことができます。 また、今回の運営にあたり、受付期間の短さ、報告に対する審査結果、等に対する不満を持たれた方もいらっしゃるかと思います。受付期間につきましては、初の試みであったため、様々な試行錯誤を想定して、1ヶ月という期間を設定させていただきました。また、審査につきましては、利用規約に準じて適正かつ慎重に実施しており、例えば、LINEがすでに把握しているものや、先行して報告のあった脆弱性につきましては、新規の脆弱性として認定しておりませんので、ご理解のほど、よろしくお願い申し上げます。 本プログラムはすでに終了しておりますが、追加でLINEにおけるセキュリティの脆弱性を発見した方は、dl_bugbounty@linecorp.comまでご報告お願いいたします。詳細については、LINE Bug Bounty ProgramのWebサイトをご参照ください。
↧
↧
LINE Developer Week 2015
LINE台湾支社でAPI開発とアプリケーション分析を担当しているAugustin Wangと申します。今回は、2015年11月に開かれたLINE Developer Weekについて、レポートしたいと思います。 韓国に到着 いよいよ待ちに待ったLINE Developer Weekの初日です!仁川国際空港からバスで1時間ほど移動して、書峴(ソヒョン)駅にあるLINEの韓国オフィスに到着しました。オフィスには、かわいいLINE FRIENDSのキャラクターと各種グッズが飾られていました。 ここでは、日本と中国から来たたくさんの仲間と出会うことができました。英語・日本語・中国語・韓国語が混ざった会話になっていましたが、LINEのエンジニア同士では言葉の壁を感じることはありませんでした。 LINE Developer Day 韓国で過ごした1週間で一番記憶に残っているのは、ソウルで開催されたLINE Developer Dayでした。数百人に及ぶ開発者がLINEの最新技術動向を知るために集まってきました。LINE Developer Day参加者の出身企業・国は多岐にわたります。では、キーノートと午後のセッションのプレゼンテーション内容について簡単にご紹介いたしましょう。 キーノートセッション キーノート (CTOパク・イビン) LINE Developer Day 2015のキーノートのテーマは、「LINE, The Platform of Today」でした。LINEのCTOを務めるパク・イビンがLINEが達成した成果を数値で紹介しました。例えば、一日に170億件のメッセージを処理すると発表しましたが、これは、LINEが日常生活において欠かせないサービスとして定着していることの証といえるでしょう。しかし、こうした成果に甘んじることなく、さらに進化したLINEプラットフォームを構築してより多くの開発者とコンテンツプロバイダーに提供できるよう、常に改善を行っています。最後に、来年開かれるLINE Developer Dayではスマートモバイルエコシステムをお披露目する計画であると述べ、キーノートを締めくくりました。 LINE Development Chronicle (キム・ドンヒョン) このセッションでは、キム・ドンヒョンがここ4年間のLINEの発展過程を紹介しました。LINEは、「誰もが」利用できるメッセンジャーという、シンプルなニーズから始まりました。今は、子供から年配の方々まで、幅広い層がLINEを利用しているので、大きく成功したといえるでしょう。また、LINEは2つの特徴的なサービスである「位置情報共有」、「既読表示」を導入しました。これらの機能により、さらに便利にLINEをお使いいただけるようになりましたが、技術的な問題も発生していました。LINEのエンジニアたちは、ここ数年間発生していた各種問題を調査し、多彩な最新技術を適用することで、アーキテクチャとアプリケーションを改善し続けてきました。こうした取り組みに支えられ、LINEのサービスの安定性と速度は向上しました。 LINE Bubble 2 Development Story (イ・テウン) イ・テウンのLINE Bubble 2 Development Storyは、最も好評であったセッションの一つでした。LINE Bubble 2の当初の計画は、開発着手から3ヶ月以内にリリースすることでしたが、様々な変更が発生したことで、制作期間が1年に延びました。例えば、元のコンセプトは、キッチンで料理をするブラウンだったそうです。しかし、メンバーの間でユーザーの持続的な関心を引き付けるには物足りない感があるという意見があり、冒険をテーマにしたストーリーへと方向を転換したのです。このゲームは、2015年4月23日に正式リリースされました。 午後のセッション LINE Channel Platform and More (パク・ヨンソプ、 高橋ホセルイス) このセッションでは、パク・ヨンソプと高橋ホセルイスが、チャネルゲートウェイやLINEプラットフォーム、 ビジネスコネクトの概念とその用途について説明しました。ビジネスコネクトのサーバは、チャネルゲートウェイを使用してLINEの各種内部サービスとデータをやり取りすることができます。 LINEプラットフォームの開発において中核となるのは、個人情報保護とセキュリティです。ユーザーの皆様に安心してオープンプラットフォームサービスを利用していただけるよう、LINEプラットフォーム担当の各チームは、個人情報保護とアビューズ行為への対応に最善を尽くしています。 LINE Game Cloud (チェ・ヨンホ、ジョハン・ガル) このセッションでは、LINEゲームプラットフォームの新しいアーキテクチャの紹介がありました。新しいプラットフォームを模索するきっかけとなったのは、LINE GAMEの急成長でした。チェ・ヨンホとジョハン・ガルの話によると、多種多様なゲームにおいて常に満足できるユーザーエクスペリエンスを提供することは、難しい課題だったそうです。彼らは、ユーザーの満足度のみならず、開発者の暮らしの質まで保障できてこそ完璧な解決策になると強調しました。また、怠け者の本人たちの仕事をより容易にするためにも、イノベーションに力を入れるべきだったと冗談交じりに話していました。 LINE for Windows 10 (クォン・オイク、ソク・ヨンテ) Microsoftは、Windows 10のリリースを機にアプリケーションストア「Windowsストア」をリニューアルしました。これは、Windows版アプリ開発の新たな出発をも意味します。クォン・オイクとソク・ヨンテは、クライアント開発者とサーバ開発者の観点からWindows 10版LINEを開発した経験を話しました。 Applying QUIC Protocol on LINE Games (ソン・ソンホ、パク・テヨン) このセッションでは、LINEゲームプラットフォームに使用されるQUICプロトコルの紹介がありました。QUICはTCPとUDPに対応しており、知的メカニズムでコネクションのハンドシェイクとパケットロスを処理します。これは、特にモバイルゲームの通信環境においては最適な方法であるといえます。 Armeria: LINE’s Next Generation RPC Layer (イ・ヒスン) Armeriaは、Java 8およびNetty 4をベースにした同期・非同期RPCライブラリです。これは、コネクションポーリング(connection polling)とドメイン名検索の問題を解決できる真の非同期RPCであるといえます。イ・ヒスンは、サンプルコードとクライアントのデモを紹介しながら、Armeriaの機能を説明しました。ArmeriaはLINEの開発にすでに使用されており、オープンソースでも公開されています。 Hardcore: Trend of Chinese Mobile Game (Longtu GameのCPO Chen Liu様) Chen Liuは、中国のモバイルゲーム市場の最新動向について語りました。中国は、進出先として誰もが注目する巨大な市場です。中国市場の現況分析の後は、LongTu Gameが良質のIP(Intellectual Property:知的財産)を発掘または創出し、RPGのようなハードコアゲームを制作する方法について説明しました。また、中国のモバイルゲーム市場の新しいニーズに応えるべく、ハードコアの特性を持ったミッドコアゲームの開発に注力していると述べました。 Ampkit: Mobile VoIP (…)
↧
Cocos2d-xにおけるマルチスレッドを利用した並列処理技法―物理演算パフォーマンスの最適化に向けて―
こんにちは。LINEでモバイルゲームの開発を担当しているSTです。今回は、オープンソースのモバイル向けゲームエンジンの世界シェア1位(25%)を誇るCocos2d-xにおいて、マルチスレッドを利用して並列処理を行う方法をご紹介します。シングルスレッドで動作していた既存の物理演算をマルチスレッド化して並列処理するように構造を改善し、パフォーマンスを向上させる方法について説明します。 マルチスレッドを利用した物理演算の並列処理構造の設計 マルチスレッドを利用した物理演算の並列処理構造を説明する前に、まず既存のシングルスレッドを利用したCocos2d-xのアップデートのループを説明しましょう。 【図1】は、Cocos2d-xにおける既存のアップデートのループです。ユーザーの入力内容を取得してゲームロジックを実行した後、物理演算を行い、最後にレンダリングするという流れです。ここで重要なポイントは、シングルスレッドなので、物理演算が終わった後にレンダリングが実施されるという点です。つまり、物理演算が終わるまでレンダリングができない構造なのです。そのため、物理シミュレーションに多くの演算が必要な場合はレンダリングに遅延が発生し、結局はFPSが低下して、カクカクとした不自然な動きの画面になってしまいます。 その逆の場合も同じです。レンダリングの演算量が多くなると、次のユーザー入力で待機が発生し、物理演算結果の更新が遅延します。これは、すべての処理が一つのループで行われるからです。演算量が少なく、処理数が多くない状況ならシングルスレッドでも問題ありませんが、過負荷の状況ではこのような問題が生じやすくなります。 【図2】は、Cocos2d-xでマルチスレッドで動作する物理演算の並列処理の設計図です。【図1】との違いは、物理演算が別スレッドで実行されるという点です。メインスレッドでは、最新の物理演算結果のみ読み込んでレンダリングします。既存のシングルスレッドでは、物理演算が終わるのを待ってからレンダリングを行っていました。 一方、新たに設計したこの構造において最も重要なポイントは、物理演算は別スレッドで並列処理されており、メインスレッドではその物理演算が終わるのを待つことなく、最新の計算結果のみ読み込んでレンダリングするという点です。また、レンダリングに過負荷がかかって遅延が発生している状況でも、物理演算は別スレッドで一定のtick※注1を保持しながら独立して並列処理できます。 アップデート方法としては、メインスレッドではゲームのプレイ時間によって結果を表示する必要があるためDelta Timeアップデート※注2を使い、Simulatorスレッドでは物理演算の精度を高めるために一定時間ごとにアップデートするFixed Timeアップデート※注3を使います。こうすると、Unityのように物理演算が並列処理されるので、開発者はFixed Time値を変えながら、つまりゲームに適した物理演算の精度を調整しながらシミュレーションできるようになります。 【図3】は、Cocos2d-xでマルチスレッドを利用して物理演算の並列処理ができるシステムアーキテクチャです。このシステムには、次の4つのモジュールがあります。 Cocos2d-x Chipmunk Physics Library Game Simulator Cocos2d-xにはChipmunk Physics Libraryという2D物理エンジンが標準で搭載されています。Gameは、Cocos2d-xを使ってゲームに必要なSceneを作成し、各種コンテンツを開発します。ここで、Scene情報を別スレッドであるSimulatorに渡すと、SimulatorはCocos2d-xにアクセスできるようになり、最終的にはCocos2d-xでChipmunkライブラリの物理演算を動的にコントロールできるようになります。ここでCocos2d-x、Chipmunk、Gameはメインスレッドで動作し、Simulatorは別スレッドで動作します。つまり、Gameと物理演算が並列に処理される構造なのです。 ※注1:tickはアップデート関数が呼び出されることを意味し、tick countはアップデート関数が呼び出される回数のことです。前のアップデートから今のアップデートまでの時間差をDelta Timeといいます。Delta Time値が小さいほどアップデートのサイクルが早くなりますが、これは言い換えると、アップデートのtickの発生頻度が高くなるということです。 ※注2:Delta Timeアップデートは、前フレームと現フレームの時間差の単位、つまりDelta Time(1/FPS)ごとにアップデートする方法です。 ※注3:Fixed Timeアップデートは、一定時間ごとにアップデートする方法です。 マルチスレッドを利用した物理Simulatorの設計 物理演算をマルチスレッドで処理するためには、物理Simulatorの設計がとても重要です。 【図4】は、既存のCocos2d-xの物理構造を示した図です。ノードとPhysicsBody、SceneとPhysicsWorldはそれぞれ1対1の関係にあります。Sceneは複数の子ノードを持つことができ、PhysicsWorldも複数のPhysicsBodyを持つことができます。このように、ゲームの画面を格納する最上位オブジェクトであるSceneと複数の物理オブジェクトを格納する最上位オブジェクトであるPhysicsWorldが1対1の構造になっています。また、イベントハンドリングのための一つのEventDispatcher変数をグローバルに使用しています。 では、既存の構造をマルチスレッド化するには、どうすればいいでしょうか。【図5】には、Simulatorが追加されています。Simulatorは、SceneオブジェクトとEventDispatcherオブジェクトを持っています。SimulatorはSceneオブジェクトを使用してPhysicsWorldにアクセスし、最終的にはPhysicsBodyにアクセスして物理データにアクセスできるようになります。ここでPhysicsBodyは、Chipmunk Physics Libraryが提供する実際のRigidbodyオブジェクトであるcpBodyをラップしたクラスです。Cocos2d-xでは、PhysicsBodyオブジェクトが Chipmunk Physics Libraryの値にアクセスしています。つまり、Cosos2d-xで物理演算を並列処理するには、Cocos2d-xのソースコードのみならず、Chipmunk Physics Libraryのソースコードにも同期化ロジックを追加しなければなりません。 同期化のために、Chipmunk Physics Libraryのソースコードをダウンロードして、cpBody値の変更箇所にMutex同期化ロジックを追加しました。なお、Cocos2d-xでもcpBodyを使用するPhysicsBodyに同期化ロジックを追加しました。特にReadの場合は、TryLockを使用してロックがかかっているかをチェックしました。ロックがかかっていれば、リリースされるまで待たずに最新の計算結果を読み込んですぐにレンダリングを行い、別のタスクを処理できるようにしました。また、Cocos2d-xでは、EventDispatcher変数一つでイベントハンドリングを処理します。そのため、メインスレッドでEventDispatcherが発生した際にSimulatorスレッドからアクセスすると、プログラムにエラーが発生する可能性があります。 この問題の解決には2つの方法があります。一つ目は、Mutexを使用してクリティカルセクションを設定する方法です。二つ目は、Simulatorスレッドに独立したEventDispatcher変数をもう一つ生成する方法です。この設計では、パフォーマンス向上を図るためにMutexを極力使用していません。その代わり、Simulatorスレッドで物理衝突イベントを直接ハンドリングできるように、SimulatorでEventDispatcher変数を宣言し、メインスレッドとコンフリクトせずに独立してハンドリングできるようにしました。つまり、Chipmunkのソースコードに同期化ロジックを追加してビルドし、libchipmunk.aライブラリファイルを作成しました。このライブラリを修正されたCocos2d-xのソースコードとともにビルドしてリンクし、最終的にlibgame.soファイルを作成しました。こうすれば、libgame.soファイルを使ってゲームを駆動できるようになります。 テスト環境 新たに設計したマルチスレッド構造で物理シミュレーションを行い、シングルスレッドのときに比べてパフォーマンスがどれほど向上したかをテストしてみました。テスト環境は下表のとおりです。テスト端末はiPhone 5sを使用し、Cocos2d-xのバージョンは3.6、Chipmunk Physics Libraryのバージョンは2.2.2を使いました。 同期化およびイベントハンドリングのテスト 物理演算をマルチスレッドで並列処理した場合、同期化およびイベントハンドリングが正常に動作するかを確認するためにテストプログラムを開発しました。テストプログラムは、Cocos2d-xに用意されているContact testの例題を活用しました。 【図6】は、テストプログラムで三角形と四角形のオブジェクトを大量に生成したものです。ここで、オブジェクト同士が衝突すると跳ね返り、画面の上下左右の端にある透明な壁に当たるとまた跳ね返ります。同期化およびイベントハンドリングをテストするために、各オブジェクトが衝突する度にコールバック関数でオブジェクトの色を緑色に変化させました。 シングルスレッドとマルチスレッドを同じ条件下でシミュレーションしました。その結果、【図7】の(a)と(b)のように両方とも緑色に変化していることを確認できました。オブジェクト同士が衝突して跳ね返るのは、同期化処理が行われたことを意味します。また、衝突したオブジェクトが緑色に変わったのは、イベントハンドリングが正常に動作し、コールバック関数でオブジェクトの色を緑色に変化させたことを意味します。こうして、同期化およびイベントハンドリングが正常に動作することを確認しました。では、次にパフォーマンス測定結果についてご紹介します。 パフォーマンス測定結果 既存のシングルスレッドに比べて、新たに開発したマルチスレッドによる物理演算がパフォーマンスをどこまで改善させたのかを測定してみました。 過負荷状態でのゲームのパフォーマンス測定結果 ゲームを開発していると、ゲーム自体が遅くなったり、過負荷がかかったりすることがあります。過負荷状態になりゲームのレンダリングの遅延が発生することがあります。その際、マルチスレッドの物理演算がどのような影響を与えるのかをテストしてみました。ゲームに負荷がかかるとCPUの演算量が多くなるので、次のとおりMatrixを複数回乗じた値を過負荷の度合いとして定義しました。 MAX_UPDATE_COUNT = 300000 updateForOverhead() for i ← 1 to MAX_UPDATE_COUNT do dstMatrix ← dstMatrix * srcMatrix こうすることで、MAX_UPDATE_COUNTという変数を使ってゲームの負荷の度合いを定量的に数値化することができます。 シミュレーションされるオブジェクトの数は360個に固定し、ゲームの負荷の度合いを最低30万から最大300万まで上げながらテストしました。【表2】のように、ゲームの負荷の度合いが30万のときは、シングルスレッドとマルチスレッド[Multi(Main) Thread、Simulator Thread]両方ともFPSの最大値として設定した60FPSに達していました。なお、300万のときは、シングルスレッドは9.1FPS、マルチスレッドのメインスレッドは9.7FPSと、ほぼ同等の数値を示していました。しかし、マルチスレッドのSimulatorスレッドでは60FPSとなっていました。 ゲームの負荷は物理演算と関係なくメインスレッドにかかるので、シングルスレッドもマルチスレッドのメインスレッドもともにパフォーマンスの低下が発生しました。一方、物理演算は、別スレッド(Simulatorスレッド)で動作するのでゲームの負荷による影響は受けず、30万のとき、300万のときいずれも60FPSとなっています。 【図8】は、ゲームの負荷の度合いによるパフォーマンス測定結果をグラフにしたものです。シングルスレッドとマルチスレッドのメインスレッドの勾配(赤線・青線)を比較してみると、マルチスレッドのメインスレッドの方がパフォーマンスの低下が緩やかであることが分かります。これは、シングルスレッドでは物理演算とレンダリングを一つのループで処理するのに対し、マルチスレッドではSimulatorスレッドで物理演算を行うからです。このため、シングルスレッドのようなパフォーマンスの急激な低下は発生しません。 上記の測定結果はストレステストから得た数値ですが、実際に適用できる有意味な数値が得られるのはどの区間でしょうか。実際に適用できる数値は30FPSであり、ゲームの負荷が90万のときの区間です(【図 8】の青い四角で囲んだ部分)。この区間の数値は、シングルスレッドでは25.3FPS、マルチスレッドのメインスレッドでは31.7FPS、そしてSimulatorスレッドでは60FPSとなっています。 物理演算をDelta Timeでアップデートするケースを分析してみると、シングルスレッドでは約0.0395秒(25.3FPS)ごとに物理演算を行い、レンダリングします。それに対し、マルチスレッドでは、0.0167秒(60FPS)ごとに物理演算を行い、0.0315秒(31.7FPS)ごとにレンダリングします。つまり、マルチスレッドの方が約2.4倍小さい値で細かく物理演算を行うので当たり判定がより正確になる上、より高いFPSでのレンダリングもなめらかになり、クオリティの面で格段の差が出ます。また、Fixed Time値を0.0167秒に設定してFixed Timeでアップデートするケースを分析してみると、シングルスレッドでは約0.0395秒(25.3FPS)ごとに0.0167の値でstep※注4しながら当たり判定の処理およびシミュレーションを行います。 一方、マルチスレッドでは、約0.0167秒(60FPS)ごとに0.0167の値でstepしながら当たり判定の処理およびシミュレーションを行います。この場合、シミュレーションするstep値が同じなので精度も同じと思われますが、マルチスレッドの方でtickが約2.4倍多く発生するので、シングルスレッドよりシミュレーションが高速化することが分かります。 ※注4:stepとはアップデートと同じで、アップデートとは物理シミュレーションを行うという意味です。「1段階ずつアップデートする」ということを、「1段階ずつstepする」とも表現します。 過負荷状態での物理演算のパフォーマンス測定結果 ゲームを開発していると、ゲームロジックまたはグラフィックの問題ではなく、物理演算自体が遅くなることがあります。このように物理演算に負荷がかかった場合、どのような変化があるかをテストしてみました。 ゲームの負荷の度合いは30万に固定し、シミュレーションされるオブジェクトの数は最低360個から最大1080個まで増やしながらテストしました。【表3】から分かるように、オブジェクトの数が360個のときは、シングルスレッドとマルチスレッド[Multi(Main) Thread、Simulator Thread]両方ともFPSの最大値として設定した60FPSに達していました。一方、1080個のときは、シングルスレッドは12.3FPS、マルチスレッドのメインスレッドは60FPSでした。しかし、マルチスレッドのSimulatorスレッドでは12.5FPSと、シングルスレッドに近い数値を示しています。 物理演算に負荷をかけたため、シングルスレッドもマルチスレッドのSimulatorスレッドもともにパフォーマンスの低下が発生したのです。それに対し、マルチスレッドのメインスレッドでは、ゲームロジックとレンダリングがSimulatorスレッドとは別に動作するので、物理演算のコストが発生せず、360個のときと1080個のときいずれも60FPSとなっています。 【図9】は、物理演算の負荷の度合いによるパフォーマンス測定結果をグラフにしたものです。シングルスレッドとマルチスレッドのメインスレッドの勾配(赤線・青線)を比較してみると、シングルスレッドではパフォーマンスが急激に低下しているのに対し、マルチスレッドのメインスレッドではFPSの最大値である60FPSを維持していることが分かります。なお、Simulatorスレッドではパフォーマンスの低下はあるものの、シングルスレッドほど急激な低下ではありません。シングルスレッドでは物理演算とレンダリングを一つのスレッドで行うのでパフォーマンスが急激に低下しますが、Simulatorスレッドでは物理演算のみ行うので、シングルスレッドよりはパフォーマンスの低下が緩やかになっていることが分かります。 上記の測定結果はストレステストから得た数値ですが、実際に適用できる有意味な数値が得られるのはどの区間でしょうか。実際に適用できる数値は30FPSであり、オブジェクトの数が760個のときの区間です(【図9】の青い四角で囲んだ部分)。この区間の数値は、シングルスレッドでは23.6FPS、マルチスレッドのメインスレッドでは60FPS、そしてSimulatorスレッドでは32.2FPSとなっています。物理演算をDelta Timeでアップデートするケースを分析してみると、シングルスレッドでは約0.0424秒(23.6FPS)ごとに物理演算を行い、レンダリングします。それに対し、マルチスレッドでは、0.0311秒(32.2FPS)ごとに物理演算を行い、0.0167秒(60FPS)ごとにレンダリングします。 つまり、マルチスレッドのときは、別スレッドで0.0311秒ごとに物理演算を並列処理し、メインスレッドで0.0167秒ごとにすでに計算された物理シミュレーション値でレンダリングのみ実行します。そのため、パフォーマンスの面では当たり判定が正確になり、動きがよりなめらかになることを確認できます。また、Fixed Time値を0.0167秒に設定し、Fixed Timeでアップデートするケースを分析してみると、シングルスレッドでは約0.0424秒(23.6FPS)ごとに0.0167のstepで当たり判定の処理およびシミュレーションをしてからレンダリングします。一方、マルチスレッドでは、約0.0311秒(32.2FPS)ごとに0.0167のstepで当たり判定の処理およびシミュレーションを行い、0.0167秒(60FPS)ごとにすでに計算された値でレンダリングします。この場合、マルチスレッドの方がシングルスレッドより正確で速いだけでなく、レンダリングFPSが約2.5倍高いため、動きが遥かになめらかになります。 当たり判定の正確性テスト 上述の通り、シングルスレッドのときに物理演算をDelta Timeで行う場合、ゲームに負荷がかかるとtickが不安定になって衝突チェックが正確にできない可能性があります。マルチスレッドで物理演算を行った際、当たり判定の正確性がどれほど向上したかをテストしてみました。テストの条件は、実際に適用できる数値、つまりマルチスレッドのメインスレッドとSimulatorスレッドがいずれも30FPSになる状況としました。アップデート方法としては、シングルスレッドではDelta Time方法を使い、マルチスレッドではメインスレッドはDelta Time、SimulatorスレッドはFixed Timeをそれぞれ使用するように設定しました。オブジェクトが壁(Bound Box)にぶつかると跳ね返らないといけないのに、すり抜けてしまうケースがあるかをチェックし、シミュレーションが開始してから経過時間ごとにオブジェクトの数を観察しました。 【表4】は、マルチスレッドで物理演算したとき、当たり判定の正確性がどれほど向上したかを測定した結果です。最初はシングルスレッドとマルチスレッド両方ともVertex(頂点)の数が5022個でしたが、15秒後にはシングルスレッドでVertexの数が6個減りました。三角形1個にはVertexが3個あるので、三角形2個が消えたことになります。さらに30秒後には4986個になり、36個が減少しました。これは、三角形12個が消えたと推定できます。一方、マルチスレッドでは、時間が経ってもずっと5022個であり、壁をすり抜けて消えたオブジェクトはなく、正確に当たり判定が行われていることが分かります。 結論および今後の課題 (…)
↧
try! Swift 登壇レポート
try! Swift に参加して こんにちは、LINEでiOSエンジニアを担当しているInami (@inamiy) です。 先日、2016年3月2日〜4日の3日間にかけて、「try! Swift」というSwiftカンファレンスが東京・渋谷で開催されました。 弊社もゴールドスポンサーとして協賛した同イベントですが、総勢500人を超える参加者のうち実に3割近くの方々が海外からの参加で、女性講演者の比率も高く、 これまでのSwift/iOS勉強会ではなかなか見られなかったようなとても国際色豊かで華やかなイベントとなりました。 私は今回、スピーカーとして登壇する貴重な機会をいただき「パーサーコンビネーター in Swift」という関数型言語のテーマについて話しました。 – スライド – GitHub – 雰囲気 – 動画: 近日公開予定 この3日間のイベントは、 try! Swift みんなの感想・レポート・考察記事 のどの感想を読んでも分かるように、 Result.SuperSuccess(event) と言っていいほどの大成功を収めることができました。 各セッションの詳細については、既にたくさんのブログで取り上げられていますので、 この記事では私個人の視点から見たイベント成功のポイントや学んだ点について書きたいと思います。 海外スピーカーはとにかくプレゼンが上手 ひとことで言って、「文化の違い」を強く感じました。 スライドの表現力・声のトーン・サービス精神・ユーモア(ポケモン、ドラゴンボール)など、 ただ単に技術スライドを見せるのではなくストーリーを織り込んで「魅せるプレゼン」をされていたと思います。 特にスピーカーの「動き」には目を見張るものがありました。 例えば Daniel H. Steinberg (@dimsumthinking) さんは独特の大きなジェスチャーが特徴的で、 まるで遠くの客席にまで声を届けるような、人を惹きつけるのに十分すぎるプレゼンでした。 また、 J.P. Simard (@simjp) さんや Adam Bell (@b3ll) さんのような、早口ながらもキレのある声と堂々とした姿勢は、 プレゼン全体を勢い付かせて、マーク・ザッカーバーグを彷彿とさせました。 Chris Eidhof (@chriseidhof) さんに至っては、落ち着いた分かりやすい口調で30分間途切れることなく圧巻のライブコーディングを披露。 スピーカー各々が自分の個性を存分に発揮し、臨場感溢れる最高の講演をされました。 国際交流(懇親会)の大切さ try! Swift カンファレンス開催前に、主催者の Katsumi Kishikawa (@k_katsumi) さんが投稿した2本のブログ記事 – try! Swift 2016を200%楽しむために – 24/7 twenty-four seven – 懇親会における英会話のプロトコル – 24/7 twenty-four seven は、今振り返ってみるととても示唆に富んだ内容でした。 というのも、当日のスライドや講演内容は後日公開されるアーカイブ記事でいつでも確認できますが、 「人とふれあう」体験はその時・その場でしか味わうことができません。 特に、海外からの参加者(スピーカー・観客問わず、皆さん凄腕ぞろい)と話せる機会はそうそう訪れないでしょう。 今回のイベントを「チャンス」と見なし、積極的に「交流」できたかどうかがイベントを「楽しむ」上での一番のポイントだったように思います。 その点において、3日目最終日のカンファレンス終了間際に、 Yuta Koshizawa (@koher) さんから参加者全員に向けて国際交流を促すスピーチをされたことは、とても勇気のある行動でした。 (主催者の Natasha Murashev (@natashatherobot) さん曰く、“the most beautiful speech” でした) そのおかげで、最後を締めくくる全体懇親会で、「初めて海外スピーカーと話せた」と喜ぶ国内エンジニアの方を何人も見かけることができたのがとても印象に残っています。 (私はこのとき、日英通訳の一人として間を取り持ちましたが、 言語・文化の壁を超えて人と人がつながっていく様を目の当たりにして、通訳の面白さを初めて知りました) タレント揃いの、万全の事前準備 これだけ素晴らしいスピーカー・オーディエンス・会場設営(株式会社 サイバーエージェント)が一同に揃ったのも、 iOS開発者として有名かつイベント主催者の Natasha さんと Kishikawa さんらのご人徳とご尽力によるものです。 (…)
↧
社内プロジェクト「Armeria」をオープンソース化するために行った6つのステップ
Armeriaは、Java 8およびNetty上に非同期RPC/APIクライアントサーバを実装したものです。LINEは昨年11月、ArmeriaをApache License 2.0のもと、オープンソースとして公開しました。Armeriaは、HTTP/2をセッションレイヤプロトコルとして使用する高性能の非同期Thriftクライアントサーバを構築するために立ち上げたプロジェクトですが、基本的にプロトコル非依存型で拡張性に優れています(例えば、HTTP/2によって静的ファイルを処理すると同時に、Java EE Webアプリケーションを起動することができます)。 今回の記事では、技術的な面にフォーカスするよりは、社内プロジェクトをオープンソース化する過程についてご紹介したいと思います。Armeriaの技術的な情報が知りたい方は、2月にLINE福岡オフィスにて開催された第14回LINE Developer Meetupで発表した資料をご参考ください。 1. プロジェクト履歴のクリーニング 社内プロジェクトを進めていると、公開プロジェクトであれば決して表に出さないはずの次のような変更履歴が多数含まれてしまいます。 機密情報(イシュー番号、ホスト名、社内URLなど) 無意味または不確実なコミットメッセージ(「Blah」、「WIP」、「WTF」など) 著作権告知ヘッダー このような文言を修正するコミットをリポジトリに追加するとしても、プロジェクトの履歴が完全に残ってしまうので、そうした作業は役に立ちません。そのため、履歴の内容を「クリーニング」しておけば、予期せぬ情報の流出を回避することができます。クリーニングには2つの方法があります。 一つ目は、変更履歴を一つ一つ検討しながら修正する方法です。この場合、git filter-branchのようなコマンドを使って自動化すれば、ある程度の手間を省くことはできますが、変更履歴をいちいち注意深く確認する必要があります。 二つ目は、流出してはいけない内容を全部修正し、複数の変更履歴を一つのコミットに圧縮する方法です。これは、一つ目の方法よりは簡単ですが、すべての履歴が失われてしまいます。既存の履歴が消えるので、後で特定のコードを書いた理由が思い出せなくても知りようがありません。 プロジェクトの履歴が比較的に短く、明確に定義されているコーディングスタイルガイドに沿ってコードを作成した場合は、一つ目の方法を選択するでしょう。一方、時間も足りず、検討すべき量も多すぎる場合は、私たちのように大胆な道を選ぶはずです。つまり、すべての履歴をたった一つのコミットにまとめてしまうのです。 ただ、最近はコードを一人で全部書くことはないため、この方法にも問題はあります。コミットを一つだけ残しておくことになると、巧みなスキルを発揮して協力してくれた多くの方の労をねぎらう方法がなくなってしまいます。そのため、結局下記のとおりコミットメッセージを残すことで感謝の意を表すしかありませんでした。 Subject: Initial import This commit contains the collective work of the following enthusiastic contributors at LINE Corporation: - Anuraag Agrawal @anuraaga - Heon Jeong @blmarket - Young-tae Seok @delegacy - Su-ahn Lee @inch772 - Woo-jung Choi @sophiechoi - Trustin Lee @trustin - Yuichi Ono 今振り返ってみると、コミットメッセージに感謝の気持ちをもっと積極的に表現すべきだったと思います。この記事をお借りして、ご協力いただいた方々に改めて厚く御礼申し上げます。 2. APIドキュメントの作成 ゼロからプロジェクトを始めるとき、特に参考にできるテンプレートがない場合は、コードを迅速に作成して早めに公開する必要があります。そうしなければ、設計上のイシューやバグを早期に発見することができません。この段階でAPIの変更が頻繁に発生しますが、実装作業に集中しているとAPIドキュメントの作成は後回しになり、いつか埋めなければならない穴として残ってしまいます(正直なところ、ドキュメントを書くことよりコードを書くことよりコードを書くことの方が遥かに楽しいということもあります)。 しかし、良いドキュメント化はオープンソース分野において中核的な要素です。よほど切実な状況でない限り、ドキュメントを提供していないオープンソースソフトウェアを使おうとする人はいません。しっかりドキュメント化されていない私たちのオープンソースプロジェクトを、誰が選択してくれるでしょうか。世の中には、すでに類似したプロジェクトが数多く公開されていることを忘れてはいけません。 結局、残しておいた穴はすべて埋めざるを得ませんでした。それを「技術的負債(technical debt)」という用語にならって「ドキュメント化の負債(documentation debt)」と呼びました。率直に言って、その負債を返すことは決して愉快なことではありませんでした。でも、一度しっかりドキュメント化してからは、負債を最低限に抑えて維持できるようになりました。パブリックメソッドやクラスを新規で作成したら、レビューしながらドキュメント化作業を平行すればいいのです。これはバランスの良い体を維持することと似ています。一度スマートな体を作っておけば、その次からは体型を維持しやすくなるという原理です。 3. Webサイトの構築 Githubはプロジェクトを提供するためのいい土台ですが、専用のWebサイトを活用するとさらに効率的です。プロジェクトのWebサイトがあれば、知りたい情報を好きな方法で構成して提供できるだけでなく、プロジェクトの性格をより視覚的かつ効果的に伝えることができます。 しかし、Webサイトの構築は簡単なことではありません。さらに、Webサイトの管理のために、コードを数行書き込む以外に多くの時間をかけたくはありませんでした。そのため必要だったのは、拡張可能な方式でWebサイトを構築・メンテナンスできるツールでした。 幸いなことに、数人のエンジニアがオープンソースで公開した素晴らしいWebサイト作成ツールがありました。このツールを使用すれば、HTMLやCSSを直接扱えるようになり、デザイナーの負担を軽減できます。そこで選択したのはSphinxで、sphinx-maven-pluginとRead the Docs themeをも併用することで、ビルドプロセスの一部としてWebサイトを作成できるようになりました。そのほかにも、Awestruct、Jekyllのように同じ用途で使用できるツールが複数あります。Webサイトの構築に興味のある方は、これらのツールを試してみて、ご自分に一番適したものを選択してみてはいかがでしょうか。 4. ロゴの作成 ロゴはプロジェクトのエッセンスと言えます。ロゴは、そのプロジェクトの目的と方向性を視覚的に、そして象徴的に表現する手段です。なお、ロゴからプロジェクトが連想され、より覚えてもらいやすくする効果もあります。 このように、ロゴはプロジェクトに重大な影響を及ぼすため、デザイナーは慎重に工夫してたくさんのプロトタイプを制作してみる必要があります。幸いにも、産業デザインを専攻したメンバーがタイミングよく入社してくれました。メインの業務で多忙な中、時間を割いてサポートしてくれて本当に助かりました。これからも今回に負けないくらい素敵なロゴを作ってくれると期待しています。 5. ライセンスの法的効力と責任に対する検討 オープンソースソフトウェアという考え方は、コンピュータ技術の始まりの頃から存在してきたものです。しかし、人々がオープンソースライセンスに関心を向けるようになったのは最近のことです。一部の人々は、無料で使用できるプロジェクトであっても、誰かに所有権があることを見過ごしているのではないかと思います。その観点からArmeriaプロジェクトでは、法的問題が発生する可能性を抑えるため、Armeriaで使用したオープンソースソフトウェアプロジェクトのライセンス条項に違反しないように、格別な注意を払いました。 その一環として、プロジェクトのリポジトリにすべてのライセンス条項ファイルとサマリーを含め、Armeriaがどのソフトウェアに助けられたのかをユーザーに明確に開示しています。なお、Armeria内でそのオープンソースソフトウェアのどの部分を修正し、再配布したのかを具体的に明記しています。 Armeriaについては、所有主体のあるオープンソースプロジェクトなので、公正かつ明確なルールに則ってライセンスを与えています。次のような特徴から、複数あるライセンスのうちApache License 2.0を選択しました。 Apache License 2.0ライセンスを採用しているソフトウェアは、無料で使用、複製、修正、頒布、販売することができ、ソースコードを開示する必要がありません。 オープンソースの特許ライセンスの付与および特許侵害に関する条項(Grant of Patent License)が明記されています。 見逃しがちなもう一つの重要なポイントはCLA(Contributor License Agreement)です。CLAは、部外者による貢献をプロジェクトに取り入れたいときに必要です。例えば、部外者が有用な機能を提案するpull requestを送った場合は、その機能をプロジェクトに反映する前に、提案を提出した人からCLAに同意する署名を受ける必要があります。CLAについて詳しく説明すると、今回の記事のテーマから外れるので割愛しますが、その代わりに関連情報を提供しているリンクをご紹介します。詳しくは、OSS WatchおよびCLAHubをご参考ください。. このような一連の過程は、多くの時間と手間がかかりそうに見えますが、実際はそうではありません。ほとんどは一回で終わる作業であり、法務部署の仲間が厄介な法的問題を代わりに処理してくれます。少しでも懸念点があれば、すぐに法務部署を訪ねましょう。 6. 多様なオープンソースプロジェクトとの協業 オープンソースプロジェクトを利用していると、バグを発見することがあります。自分で解決策を講じることもできますが、そうならない場合もあります。元のプロジェクトをフォークして自分用のプロジェクトを作成し、直接修正・管理することもできますが、それよりもっと効率的なのは、アップストリーム(upstream)に変更を提案する方法です。そうしないと、いつまでもプロジェクトを直接管理しなればなりません。なお、アップストリームに貢献すれば、オープンソース業界で自分の活動をアピールでき、他の人との協業でさらなる楽しさを味わうこともできます。このようなことは、いずれも皆様の経歴にとってプラスになるに違いありません。 Armeriaの開発に取り組んでいる間、Nettyプロジェクトで様々なイシューを発見して報告しました。一部のイシューについては、修正作業を手伝ったこともあります。 HTTP/1およびHTTP/2関連 (…)
↧
↧
LINE Trial Bot SDK ができるまで
はじめに LINE株式会社の松野です。 先日、LINE BOT API Trial Accountが発表され、熱狂的に世界中のデベロッパーに迎えられました。今まで契約を締結した企業デベロッパーしか開発することができなかった LINEのBotアカウントを個人でも簡単に開発できるようになったからです。 そういった中で、なぜ我々がLINE BOT API Trial AccountのSDKを開発するに至ったのか、そしてどうやって1週間でリリースできたのか。その経緯について以下に解説させていただきます。 Bot SDK を作ることになったワケ LINE BOT API Trial Accountが公開されてからまもなく社内でもたくさんのエンジニアたちが 開発にとりかかりました。 そこで、彼らは気づいてしまったのです。。 この API を使ってボット作るの大変なのでは?? と。 特に、Java などの静的言語の場合には、JSON をマッピングするためのクラスをゴリゴリと書く必要があります。LINE BOT API Trial Accountの場合には、API のエンドポイントも多く、やりとりするメッセージタイプもたくさんあるため、テキストメッセージ・画像・スタンプ・リッチメッセージ etc. と、幾つものクラスを実装する必要があります。LINE Developers に書いてある大量のテーブルからクラスを起こすのは極めて苦痛であり、 これは大変だ! と思ったわけです。 社内チャットでそのような話をしていると、他にもそのように感じている人間が何人もいることがわかりました。 そして、いろいろ話しているうちに LINE BOT API Trial Accountを多くの人に使ってもらうには SDK を公開するしかない!!! ということになりました。 さて、そうなってくると、エンジニアをかき集めて一気に各言語の SDK を書こうということになります。メジャーかつ社内で優秀なエンジニアが集められる言語を中心に開発しようということで、まずは何はなくとも弊社の開発の中心であるJava と Perl の開発を行うことにしました。さらに、Ruby, PHP は手を上げるエンジニアがいたため、またそれ以外にも静的言語である golang の開発は必要だろうという話になり、それぞれ開発を行うことにしました。 開発は始まってしまうと早くて、一週間程度で各言語の実装が出揃いました。 SDK を書くにあたって、心がけたところは以下の5点です。 各言語の API メソッド名などを揃える 言語ごとにあまりにもインターフェースが異なっていると、ユーザーにストレスを感じさせることになります。 各言語に精通したエンジニアを集めて書いてもらう 各言語のコミュニティの標準的な作法に則ってリリースしてもらうことが好ましいため、各言語のモジュールレポジトリにすでにリリース経験のあるエンジニアが開発することにしました。 品質を担保するために、レビューを徹底して行う 各言語の lint 的なものを設定して、良い品質を保つようにしました。 セキュリティチェックを行う 依存モジュールをできるだけ少なくする 依存モジュールをできるだけ少なくする 依存モジュールが増えれば学習コストが上がります。 Rubyの ActiveSupportのようなロードするとグローバルに組み込みクラスに影響を与えるようなライブラリは利用しないようにしました。 そういうわけで、LINE BOT API Trial Accountがリリースされました。めでたい。 Trial Bot SDK for Java の構成 以下、自分が担当した Java SDK の構成について解説します。 サポート対象の Java バージョンは 8 としました。LINE BOT API Trial Accountは Trial ということもあり、新しく環境を作るケースが多いと考えました。 Java の場合、module は細かくわけるのが一般的なので、細かくわけていきました。どの粒度に構成するかは悩みどころですが、無理のない粒度で分けました。 line-bot-model (…)
↧
AWS SUMMIT TOKYO 2016参加記録
こんにちは。LINEの鈴木です。 AWS SUMMIT TOKYO 2016が6月1日から3日にかけて開催されました。私は開発環境改善とサービス開発支援に従事していますが、近年のDevOpsにおいて Amazon Web Services (AWS)のサービスや関連事例は見逃すことができません。今回はこのイベントに参加してまいりましたので、弊社におけるDevOpsの実践と比較しながらセッションを振り返ってみたいと思います。 AWS SUMMITとは その名の通りAWSに関するや事例や活用方法がAWSサービス提供側からだけではなくAWSを利用している企業からも様々な視点から紹介されるカンファレンスです。 私は LINE に入社する前に何度か参加したことがありますが、入社してしばらく経ちますので実に数年ぶりの参加です。General ConferenceとDeveloper Conferenceの2つが並行して行われていましたが、私は主にDeveloper Conferenceのセッションに参加しました。 弊社におけるDevOps 今回いくつものセッションで”DevOps”という単語を見聞きしました。その中には、オーディエンスが誤った解釈をしていると「◯◯を使うことが”DevOps”である」という主張をしているようにしか聞こえないのではないかというセッションもいくつかあったように感じました。 クラウド環境でコンテナを BlueGreen Deployment によって配布したり、モダンなプロビジョニングフレームワークを用いたり、CI を活用していくことが”DevOps”なのでしょうか? Effective DevOpsでは一貫して”DevOpsは文化である”と説明しています。5000万デプロイ/年の実現や特定のツールや手法に頼ることそのものなどは結果的にそうなったというだけであって、それらを以って”DevOps”ではありませんよね。私たちの実践するDevOpsにおいては、「現在どういう問題があり、それを解決するためにはどのようにしたらよいのか」という視点が常に最初にあります。 あえて特筆するようなことではないように思えるかもしれませんが、「銀の弾丸」を求めてツールを選定することは非常にナンセンスですし、特定の何かによって誰しもの問題を等しく万能に解決することなどできるわけはありません。 ツールなどは現在の文化や方向に基づいて変化を推し進めるための加速器でしかなく、協調や親和の上で大きな力を発揮するものでしょう。私たちは常にそのように考えながら業務にあたっています。 開発文化 LINEの開発現場では、トライアンドエラーを容易に繰り返すことができる雰囲気があるように感じています。 トライアンドエラーのサイクルを多く繰り返せるということは多くの新しいアイデアを早期に試すことが出来るということになりますし、方向性を間違えていたとしてもすぐに新たな挑戦に向かって切り替えることがやりやすい土壌であるといえます。 失敗という経験がフィードバックを生みますし、フィードバックは次に生まれるアイデアの穴を埋める、あるいはより良くするために必要となります。 こういった文化についてはKeynoteやDevOpsに言及する多くのセッションの中で一貫して同じように説明されていました。 あるセッションの中で、日本企業では海外企業と比べて能力は遜色ないはずなのになぜ海外事例のようにうまくいかないのかという疑問に対して、失敗を許容する度合いの問題なのではないかという回答がありました。 前述したように私たちの実践するDevOpsにおいては協調と親和にまずは重きを置くという考え方があります。 失敗をするのも、失敗を許さんとするのもまた人です。 過度に失敗を恐れずに新しい挑戦をしやすいようにBlamelessnessな文化づくりに貢献することも私たちの重要なミッションのうちの1つです。 弊社サービスのプロダクション環境 LINE のサービスの多くは自社で管理されている巨大なオンプレミスの環境から提供されています。 それら潤沢な IT リソースが専任のプロフェッショナルチームによって管理されています。 データストアもまた専任のチームに多くを任せることが可能な体制ですし、セキュリティについても専門チームによって堅牢性が担保されています。 また、AWSほど多機能ではありませんが少しの操作でサーバインスタンスを作成出来るインターナルなクラウドサービスも有しています。 このサービスはコーポレートストラクチャと連動していますので、作成完了を以って自動で適切なログイン権限が設定されます。 このような運営体制が確立していますので、開発者はわずかな労力で開発環境からセキュアなプロダクション環境までを自分の管理下に簡単に揃えることが可能です。 パブリッククラウドサービスを利用することで得られる利点の1つとして挙げられる、「必要なものを迅速かつ簡単に準備することが出来るために開発者は本来するべきことだけに集中しやすい」という観点においては遜色がないのではないでしょうか。 一方で、必要なときに必要なだけのリソースを確保し、必要な時期が過ぎたら廃棄するという所謂ディスポーザブルなインフラストラクチャを実現するという点では、パブリッククラウドサービスのスピードには及ばないためになかなか実現が難しい体制であると言えますが、これはそもそもクラウドとオンプレミスの特性の差に過ぎないでしょう。 しかしながら私たちは盲目的にパブリッククラウドサービスを利用することを否定しているのではなく、今後条件が合えば利用していく可能性も十分にあります。 弊社プロダクションサービスのデプロイメント 現在弊社では多くのプロジェクトが、PMC という名前の内製のフルスタックなデプロイメントシステムを用いて各々管理されています。(PMC については、昨年の LINE DEVELOPER DAY 2015 の一部セッションの中でも少しだけ触れられています。) PMCはデプロイメントシステムですから、当然ながらデプロイをより効率化するための機能を持っていますし、その他にもインベントリ情報の管理や権限管理、プロビジョニング、ログ管理など様々な機能を有するフルスタックなアプリケーションです。 そして、日々変化していく開発者の要求に応えるべく私たちはPMCのアップデートを継続して行っています。 私たちのサービスは日本の開発拠点だけではなく、諸外国の開発メンバーと協力して開発が行われています。 またいずれかの拠点でローンチまでを担当し、機能追加などは別の拠点に移管されるということも日常的に行われています。 デプロイメントをはじめとするプロジェクトマネジメントの方法が統一的でないと、それらの引き継ぎのために多くの時間を費やさなければならなくなってしまいます。 PMCはそういった問題も解決するために、内製でフルスタックで構成されています。 しかし一方で、歴史的な積み重ねによって PMCは巨大なモノリシックアプリケーションに成長してしまっており、機能追加や改修にかかるコストが無視できなくなっています。 そこで現在では私たちは新しい機能を提供する場合や既存機能の改修を行う場合で、その機能が独立性の高いものである場合は単独のアプリケーションとして開発を行い、PMCとの連携は API 経由で行うようにするというようなアプローチを取っています。 事例セッションの中でCodePipelineが紹介されていましたが、デプロイを如何にわかりやすく効率化するかという観点において、PMCをアップデートしていく上で非常に参考にすべき点が多いと感じました。 CodePipelineはCodeDeploy, CloudFormation, ElasticBeanstalkなどと上手に組み合わせて利用することで絶大なパワーを発揮するサービスでしょうから、AWSでサービスを提供している場合にはとても魅力的なものでしょう。 PMCには効率化された配信、ビルドやCIとの連携の仕組みが既にあります。 それらを前述したようなMicroservices化するにあたり、効率的に連携させることを考える場合に大いに参考に出来ると感じました。 総括 これまで述べてきたように、私たちのミッションは開発者が本来すべき本質的なことに集中することが出来るような文化を伝導し、環境を維持していくことです。 したがって、何が何でも全てをツールを内製して解決するという考えでなく、今後の開発現場の需要によっては AWSを利用するということを選択することもあるでしょう。 いずれの場合においても、クラウドネイティブな環境下で培われたノウハウを体験しておくということは、選択の幅を広げることに繋がりますから非常に大きな資産となることでしょう。 謝辞 今回私たちは自分たちのなすべきことの本質は何かということと、今まさに行っていることが正しいアプローチであるのかどうかということを客観的に見直し、再考することが出来ました。 素晴らしい機会を提供していただき大変感謝いたしております。 また、本エントリを最後までお読みいただきありがとうございました。 エンジニア募集中! お決まりの締めで甚だ心苦しくはありますが、私たちはLINEの開発現場をより豊かにしていくための仲間を募集しております。 皆様のご応募をお待ち申し上げております。 DevOpsエンジニア【全事業対象】 DevOpsエンジニア(インフラプラットフォーム)【全事業対象】
↧
安定した love を提供するために
LINE株式会社のmoznionです。 私の所属するチームではLIVEという動画配信サービスを開発しています。芸能人や有名人の生配信やコンサートの様子の中継など様々な映像コンテンツが日々配信されているホットなサービスとなっておりiOS/Androidアプリと共にPCブラウザをサポートしています。 本記事ではこのLIVEにおける連打を支える技術についてご紹介します。 背景 iOS/AndroidのLIVEアプリには、動画プレイヤー上に配置されている「ハート」を押すことで配信者を応援するというシステムがあります(図中1)。視聴者はこの「ハート」を連打することが可能であり、それに呼応してプレイヤー画面に表示されるカウント、すなわち「すべての視聴者が押した『ハート』の数」が増えていくというインタラクションを得ることができます(図中2)。この数字が増えることで配信者はファンの応援を感じることができますし、視聴者は数字がどんどん増えていくさまを目のあたりにすることで配信に対する一体感や熱狂を感じることができるかもしれません。 ところで、開発者の間ではこの「ハート」機能全般のことを指して“love”と呼んでいますから、本記事でも以降は“love”と呼称することとします。 サービスの特性上、人気のあるアイドルの生配信などは莫大なloveが突発的に送られてくるため、サービスを落とさないようにこれらのリクエストを効率的にさばく必要があります。そうした大量のユーザが連打可能かつインクリメンタルなカウンタを、LIVEではどのようにして高可用かつある程度の即時性を持たせて実装しているかを以降で紹介します。 アーキテクチャ 概略図を以下に示します。以降のトピックで、この図に示した内容の詳細を解説します。 はじめの一歩 安定してサービスを提供するためにすべきことの1つとして、「リクエストの数を減らすこと」が挙げられると思います。これは多くの場合に当てはまる本質的な解決法です。 あくまで例ですが、loveが1回タップされる度に1リクエストを発行して、サーバに問い合わせて諸々処理をしてからリクエストを返す、というような実装をしていてはあまりに無駄が多く、またスケールしにくくなってしまいます。事と次第によってはネットワークのレイヤで詰まってしまうかもしれません。それではあまりに大変です。 そうした理由から、クライアントサイドでまとめてリクエストを送ってもらうことで総リクエスト数を減らすという解決策に至るのは自然の成り行きと言うことができるでしょう。 例えば「あるタイムウィンドウ内に何回loveをタップされたか」をクライアント側でバッファリングしてもらい、タイムウィンドウから抜ける際にそのカウントを含めたリクエストをサーバに投げるというような素朴な手法を考えることができます。そしてサーバはそのカウントを受け取り、保持しているカウンタをそのカウント分インクリメントするというような具合です。 LIVEでは純粋なカウントの代わりに、「動画の何秒時点を再生している時にloveがタップされたか」という動画のタイムスタンプをリストとしてバッファリングし、クライアントから送ってもらうというアプローチを採ることで、視聴者1人あたりのリクエスト数を削減することに成功しています。なお、「タップされたタイムスタンプのリスト」を送信しているのは後に分析用途で利用するためです。分析については後述します。 また、こうした仕組みを採用する場合はチート対策もしっかりと講じておく必要があります。例えば悪意あるユーザが1つのリクエストに大量のカウントを乗せてきた時に、それを額面通り受け取ってしまっては目も当てられません。LIVEではチートについてもしっかりと対策を講じています。 高速なストレージを使う ライブ配信中はその配信にアクセスが集中するため、同時接続する視聴者数が多くなります。そして同時接続する視聴者数が多くなれば多くなるほどloveに対するリクエスト数も多くなります。 そこでLIVEでは、RDB(LIVEではMySQLを利用しています)にloveのカウントを持ち、loveのリクエストを受けるごとにインクリメントするという風に都度DBアクセスを生じさせるよりも、インメモリのKVSにカウンタを持っておきそれに対してアクセス・インクリメントを行うことで効率的にIOを処理するという手法を採用しています。 LIVEではRedisのversion 3からサポートされているClustering機能を用いてRedis Clusterを構築しており、loveのカウンタでもそのRedis Clusterを利用しています。Redis Clusterはそのspecにもあるように、高いパフォーマンス、高い可用性、そしてスケールアウトのしやすさを誇るインメモリのKVSです。LIVEではloveの他にも様々な用途でこのRedis Clusterが利用されています。 内部の処理としては、リクエスト経由で受け取ったタイムスタンプのリストのサイズを取り、配信に対応するRedis内のloveカウンタをそのサイズ分だけINCRBYによってインクリメントする、という具合になっています。 またライブ配信の終了時に、その配信に対応するカウンタの内容をRedisからMySQLにflushし、その後にRedisからそのカウンタは削除しています。これはRedisには永続的なデータを残さず、ミニマルに利用したいという理由からです。永続的なデータはRDBに任せ、揮発しても問題が無くなおかつスループットが求められる用途(例えばキャッシュや今回のloveのような)にはRedisを用いるという棲み分けが行われています。 なお本筋とは関係ありませんが、私たちのチームではRedisを使う際にエントリのkeyの前にname spaceを付与する運用をしています。例えば[service-name]|[phase]|[entry-key]という具合です(phaseの部分には、本番環境であれば“release”、ステージング環境であれば“staging”などといった文字列が入っています)。こうすることで、key名を見るだけでどのサービス、どのフェイズなのかをひと目で判断することもできますし、うっかり別のサービスやフェイズのエントリが紛れ込んでもサービス自体に影響を及ぼさずに済むというメリットも得られます。また、prefixをもとにしてサービスやフェイズごとの統計情報も取ることができます。詳しくは以下のブログ記事が詳しいので併せてご参照下さい(なお参照ブログ記事ではmemcachedがトピックとなっています)。 http://blog.nomadscafe.jp/2013/07/cachememcachedfast.html シンプルなデータ構造を扱う 保持するデータ構造、またリクエストに乗せるデータ構造をシンプルに保つというのは、高いスループットを実現するために必要なことの1つです。特にインメモリのKVSの場合、データ構造が複雑になればなるほどストレージに乗せにくくなりがちですし、所望のデータを簡単に参照し、抜き出してくるのも難しくなります。 そこでLIVEでは、Redis内に単純なカウンタのみを作成し、そのエントリに対してINCRBYを発行することで値の更新、GETを発行することで値の取得、DELを発行することでカウンタの破棄、という具合にシンプルな操作で必要とする機能を実現できるようにしました。 また、適切なデータ構造を選択するというのも肝要となるでしょう。 例えばある配信に対するloveについて、「視聴者ごとの送った数ランキング」のような見せ方をしたい、というようなある程度複雑な用途であれば、シンプルなカウンタを用いてアプリケーション側で集計してランキングを組む、という方法よりもRedisの持つSorted Setを1つの配信と紐付けた上で、scoreをloveのカウント、memberを視聴者IDにして、ZRANGEあるいはZREVRANGEを用いて簡単にランキングの構造で引いてくる方が楽ですし効率的でしょう。 ドメインに応じて、用途に沿っていてなおかつ最もシンプルなデータ構造を選ぶことが高いスループットを維持する為の勘所と言うことができると思います。 データ分析 LIVEはloveのカウントをインクリメントするタイミングで、同時にfluentd経由で自社内のHDFSストレージに分析のためのログを投げています。ログの内容としては、「動画中のどのタイミングでloveがタップされたか」といったものをはじめとした様々なデータがあります。そして、収集されたログをHiveやPrestoを用いて分析し、サービス品質の向上に役立てています。 前述した「シンプルなデータ構造を使う」というのはサービスのスループットを上げるために必要な要素でしたが、とは言えそのデータについて分析したくなるというのが人情です。しかし、これらを同時に満足させようとするとどこかで無理が来てしまうか、あるいは相応のコストを支払って解決する必要が出てきてしまいます。従ってLIVEでは、主たる処理と並列して複雑なデータをlogger(今回はfluentd)を用いて収集してHDFSに溜め込み、その溜め込んだ内容を別コンポーネントで別途分析するという構成を採っています。 このようにサービスを提供するコンポーネントとデータを分析するコンポーネントを分離することで、データ分析時に高負荷が生じてもサービスの提供には影響を及ぼさずに済みますし、その逆もまた然りです。そしてサービス側で必要になった段階で、データ分析コンポーネントにリクエストを送って分析結果を取得してくるという方法で分析結果をオンデマンドに取り込んでいます。 分析についてはリアルタイム性はそこまで求められていない、というサービスの特性からこのような仕組みとなっています。 サーバを分離する LIVEはloveのカウントをインクリメントするタイミングで、同時にfluentd経由で自社内のHDFSストレージに分析のためのログを投げています。ログの内容としては、「動画中のどのタイミングでloveがタップされたか」といったものをはじめとした様々なデータがあります。そして、収集されたログをHiveやPrestoを用いて分析し、サービス品質の向上に役立てています。 全てを同じAPIサーバで取り扱った場合、特定のコンポーネントの負荷が極まると他のコンポーネントを巻き込んでしまい、最悪の場合サービス提供が不可能な状態に陥ってしまうかもしれません。高負荷が見込まれるコンポーネントはあらかじめ別のサーバに分離して運用することでこうした事態を防ぐことができます。 また、負荷が高まってきたらそのサーバを増強することでスケールアップ・スケールアウトすることもできます。例えば、突発的な負荷上昇した時にアプリケーションエンジニアが不在の場合でも、インフラの面倒を見ることのできるエンジニアやオペレーションエンジニアのみでもその場の対応が出来る、などといった柔軟性のある運用が可能となるでしょう。 まとめ 以上のトピックをまとめると以下のようになります。 リクエストの数を根本的に減らす。チート対策もしっかり行う。 場合に応じて高速なストレージを使う 高いスループットを実現するためにシンプルなデータ構造を用いる データ分析がリアルタイムに行う必要が無い場合はデータだけをどんどん溜めてゆき、別コンポーネントで分析させる 高負荷が見込まれるコンポーネントは別のサーバに分離して運用する 以上がLIVEにおける連打に対する取り組みでした。 このloveの機能はiOS/Androidのアプリをインストールし、LINEアカウントでログインすると利用可能になりますので興味のある方は是非お試し下さい。 最後になりますが、LINEでは映像や連打に興味のあるエンジニアを募集しています! サーバサイドエンジニア【LINE GAME】【ファミリーアプリ】【LINE Pay】 サーバサイドエンジニア【LINEプラットフォーム】
↧
LINE Fukuokaの開発拠点が新しくなりました
こんにちは、LINE株式会社で技術イベントなどを担当しているKushiiです。 LINEでは東京をはじめとして国内では福岡や福島、国外では韓国・台湾・タイなどに開発拠点があり多くのエンジニアたちがコードを書いています。 今回は、LINE Fukuokaがオフィスを移転し、エンジニアたちが働く環境も刷新されましたのでご紹介したいと思います。 場所は博多駅直結のJRJP博多ビル。オフィスエントランスではLINEのキャラクターたちが出迎えてくれます。 エンジニアの執務スペースは白で統一され、天井を高く設計しています。 移転に伴い、技術書の整理を行うと共にオライリー社の技術書を全巻取り揃えました。 全席を昇降可能なデスクに統一しています。 椅子はアーロンチェアをはじめ5種類から好みのものを選ぶことができます。 座席の間隔に余裕をもたせることでディスカッションも活発に行われています。 打ち合わせスペースは様々なスタイルでコミュニケーションが出来るよう自由度が高く設計されています。 こちらのソファーは一部が可動するようになっています。 セミナールームには60名ほどが収容可能です。 テレプレゼンスルームは他拠点とのビデオ会議がスムーズに行うことが出来る設備が導入されています。 休憩や打ち合わせなどが出来るカフェでは勉強会なども出来るようになっています。 時にはリラックスしながらコードを書くこともありますよね、そんな時はこちらのスペースを活用しています。 カフェカウンターでは淹れたてコーヒーが提供されます。 以上、一部ですがLINE Fukuokaの様子でした。オフィスが新しくなるのは福岡だけではありません。LINEは2017年1月に現在の渋谷ヒカリエから新宿のミライナタワーに移転を予定しています。今後も開発拠点の様子などを紹介していく予定です。 ご意見やご感想はこちらから!
↧
↧
LINE DEVELOPER DAY 2016 開催のお知らせ
こんにちは、カンファレンス担当のKushiiです。 LINE DEVELOPER DAY 2016 を開催いたしますのでお知らせいたします。 当イベントでは、弊社エンジニアチームの様々な経験や国内外での技術的なチャレンジ、最新の製品について発表させていただきます。各セッションでは、セキュリティ関連やBOTなどLINEが現在どのような課題を持ちどのように解決しようとしているのかも共有できればと考えております。 開催概要 開催日時 9月29日(木) 10時開場、18時半終了予定 場所 渋谷ヒカリエ 9F ヒカリエホール 参加費 無料 懇親会 イベント終了後、同じ会場で開催予定です 対象 アプリやWebなどの開発に関わるエンジニア 応募方法 7月下旬を目処に応募フォームをお知らせいたします。 サイトの更新情報、参加応募開始のお知らせなど、当イベントのお知らせをお届けするLINE公式アカウントをご用意いたしましたので是非ご登録ください。 昨年のイベントの様子は動画と資料をあわせて掲載していますので是非ご覧ください。 LINE DEVELOPER DAY_2015 Tokyo Twitter 公式ハッシュタグ #linedevday
↧
分散サービス環境へのCircuit Breakerの適用
LINEエンジニアのonoです。この記事では、LINEのサーバで実際に導入を始めているCircuit Breakerという仕組みについてご紹介します。 Circuit Breakerとは? LINEをはじめとする昨今のWebやアプリのバックエンドサーバシステムは、お互いにAPIやRPCで接続された多数のサービスのネットワークとして構成されるようになってきました。 もしこのネットワークの中の1つが突然全く応答を返さなくなったらどうなるでしょうか? ダウンしたサービスに対するアクセスがタイムアウトするまでブロックすることにより、依存するサービスまでもが連鎖的にダウンしてしまう可能性があります。 もしネットワークの全容を誰も把握できていなかったら、根本の原因がどのサービスにあるのか発見するのに時間がかかってしまうでしょう。 我々はこのような障害の連鎖を防がなくてはいけません。少なくとも、最も重要な機能が影響を受けないようにする必要があります。 そのためには、障害がおきたサービスへのアクセスを遮断しなければなりません。 この仕組みを自動化したものが、Circuit Breakerです。 http://martinfowler.com/bliki/CircuitBreaker.html 上のMartin Fowler氏の記事が詳しいですが、ここで簡単に説明します。 Circuit Breakerとは、リモートアクセスの成功/失敗をカウントし、 エラー率(failure rate)が閾値を超えたときに自動的にアクセスを遮断する仕組みです。 Circuit Breakerはステートマシンとして表現できます。 アクセス成功や失敗といったイベントが発生するたびに内部状態を更新し、障害の検出と復旧の判断を自動的に行います。 それぞれの状態と遷移の条件は以下の通りです。 CLOSED 初期状態です。全てのアクセスは普通に実行されます。 OPEN エラー率が閾値を超えるとOPEN状態になります。全てのアクセスは遮断(fail fast)されます。 HALF_OPEN OPENから一定時間たつとHALF_OPEN状態になります。アクセスを試行し、成功するとCLOSED、失敗するとOPENに戻ります。 Circuit Breaker for Armeria ArmeriaはLINEがオープンソースとして公開している、Nettyベースの非同期Thriftクライアント/サーバライブラリです。Armeriaの素晴らしいところは、decoratorによって機能を簡単に拡張できる点です。 そしてArmeria 0.13.0より、Circuit Breakerをdecoratorとして追加できるようになりました。 Circuit Breakerを使ったThrift Clientの初期化は次のようになります。 Iface helloClient = new ClientBuilder("tbinary+http://127.0.0.1:8080/hello") .decorator( CircuitBreakerClient.newDecorator( new CircuitBreakerBuilder("hello").build() ) ) .build(Iface.class); 簡単ですね。 そして、このThrift Clientを呼び出すコードは次のようになります。 try { helloClient.hello("line"); } catch (TException e) { // error handling } catch (FailFastException e) { // fallback code } Circuit Breakerが障害を検知すると、Thrift ClientはFailFastExceptionを投げるので、適切なフォールバックコードを実行します。 非同期Clientの場合も同様です。 helloClient.hello("line", new AsyncMethodCallback() { public void onComplete(Object response) { // response handling } public void onError(Exception e) { if (e instanceof TException) { // error handling } else if (e (…)
↧
LINE Game AirBorne DataCenterのご紹介
以前の記事「Spark、Mesos、Zeppelin、HDFSを活用した大容量セキュリティデータの解析」に続き、今回はAirArmor※注1から得られる検知情報をほぼリアルタイムで処理するために使用したクラウド技術とストリーミング処理方式についてご紹介します。 ※注1: LINEのゲームセキュリティ開発室で開発し、LINE Gameに適用しているモバイル向けゲームセキュリティソリューションの名称 AirBorne DataCenter & Mesos (with DC/OS) Apache Mesosをベースにセキュリティデータを解析する全体的な仕組みをAirBorne DataCenterと称しています。この仕組みには、ビックデータを処理するためのKafka、Spark、Elasticsearch、Hadoop、Zeppelin、Springなどのオープンソースが含まれています。 導入の背景 2015年初頭にスタートしたAirBorneは、大量のデータを迅速に照会することを目的に作られたものです。MesosベースのSparkを主に使用しており、データの照会およびビジュアライズ(可視化)のためにZeppelinとSpringを採用しています。これにより、DBMSで対応しにくい大量のデータの処理やJSON形式の大量のDBデータとログデータの処理など、これまで不可能または困難だった処理が可能になりました。なお、ユーザビリティの改善と解析タイプの増加に伴い、物理的なノードの拡張や各エンドポイントのモニタリングといった業務の自動化、高いユーザビリティ、安定性などへのニーズが継続的に発生しました。 特に、定期的にデータを処理する業務だけでなく、リアルタイムでデータを処理してその都度通知を受け取り、変化量をコントロールできるようにする業務も必要となってきました。 このような業務環境の変化を受け、AirBorne DataCenterの構造の設計を見直し、リアルタイム処理に対応する新しい領域を追加しました。 Apache Mesosは、多数の物理的なノードのリソースを論理的に一つのリソースとして提供できるように、フレームワークを提供しています。Kafka、Elasticsearchのように固定されたリソースを使用するケースもあれば、Spark Executorのように余分のリソースを瞬間的に最大限に活用するケースもあるなど、リソースの無駄を省き、効率的な使用を図ることができます。なお、Constraint、Role、Quotaなどを設定することで、様々な方法でリソースを予約できるようになります。 DC/OSは、Mesosフレームワークに対応するオープンソースパッケージを提供しています。Kafka、Elasticsearch、MySQL、Spark、Zeppelinなど多様なオープンソースがパッケージでサポートされます。基本的には、パッケージのインストールと運営のためのツール、障害対応、柔軟な水平拡張などの追加機能が含まれています。一定期間のテストと試験運営を経てユーザビリティの検証を終え、一部の領域に導入しています。 ストラクチャー AirBorne DataCenterは上図のような構成となっており、データ処理をリアルタイムと非リアルタイムに区分しています。データ処理においてリソースを予約・活用する方法、対象となるデータの保存期間もそれぞれ異なります。そのため、リアルタイムデータ処理については、適切な量のリソースを固定的に予約・活用するようにしました。一方、非リアルタイムデータ処理については、長期間のデータを保存するシステムで余分のCPUとメモリリソースを活用するように設計しました。 DC/OSは、上記のような環境を迅速に構築できるというメリットを持っていますが、DC/OS一つでAirBorne DataCenterの二つの領域(DC/OS AとDC/OS B)を運営するには、設計コンセプト上まだこのソリューションに適していない部分がありました。ただ、今回のプロジェクトでは、リアルタイムデータ処理環境の早期構築や柔軟な拡張、モニタリングの自動化などにおいてはDC/OSが大きく貢献しました。今後、独自の環境に適したMesosベースの開発プロジェクトを準備する予定です。 ビックデータを処理するためのパッケージで構成されているクラウド環境は、マルチユーザーのためのシステムというよりは、余分のリソースを大きな作業に活用したり、固定されたリソースを小さな作業に予約しておいたりと、リソースを自由に操作できるという観点から通常のクラウド環境とは大きく異なるといえます。実際、リアルタイム処理の場合は、対象が1,000万件あるとしても100個の処理部で並列処理すれば、一つの処理部が担当するのは10万件のみとなります。リソースが多い大きいノードを使用して拡張するとリソースが余ってしまいますが、適量のリソースを持つノードを使用するとリソースの余剰を最小限に抑えて拡張することができます。 このように、AirBorne DataCenterの構成におけるMesosは、多様な方法でリソースを予約して使用するための重要な役割を果たしています。 特徴 AirBorne DataCenterは、次のような特徴があります。 Web UIを用いたクラスタの運営(パッケージのインストール、スケールアウト)とモニタリング Mesosベースの多様なビックデータ関連オープンソースパッケージに対応 柔軟な拡張 Quota、Constraint、Roleの設定よる多様なリソース予約方法 OAuthによる認証/認可の提供 障害対応 リアルタイムデータ処理と非リアルタイムデータ処理との比較 DC/OS A DC/OS B 用途 リアルタイムデータ処理 非リアルタイムデータ処理 性能 30万EPSの処理能力 1日前のデータを5秒以内に照会(in memory) 全日付のデータを処理(in HDFS) Mesos quota Cluster:UNIQUE Role: *, Spark, HDFS Spark: 16 CPUs, 32GB memory HDFS: 4 CPUs, 8GB memory, disk * Spark mode Standalone mode Mesos coarse mode Business logic feature Local & global data aggregation Message transformation & filter Programmatic data processing Message transformation & filter Machine learning & graph Tools Elasticsearch: search, aggregation Kibana: (…)
↧
チャネルゲートウェイへのCircuitBreakerの適用
はじめに Circuit Breakerの紹介記事を先に読むことを推奨します。 チャネルゲートウェイにCircuitBreakerを適用する チャネルゲートウェイサーバは、LINEの多様なサーバの機能をCP(Contents Provider)に提供する役割を担っています。そのため、チャネルゲートウェイサーバは接続されているサーバに大きく影響されます。なお、そうした影響はチャネルゲートウェイサーバ全体に容易に拡散します。 この問題の解決に悩んでいたところ、CircuitBreakerに関する内容を聞きました。特定のサーバに障害が発生した場合、CircuitBreakerがそれを検知してそのサーバに投げられるリクエストを遮断すれば、問題を十分解決できると思いました。そのため、チャネルゲートウェイにCircuitBreakerを適用することを決めました。 チャネルゲートウェイ用のCircuitBreakerを直接実装することもできましたが、Armeriaにすでに見事なCircuit Breakerが実装されていました。ArmeriaのCircuitBreakerは、様々なオプションをニーズに合わせて設定し、CircuitBreakerBuilderで実装されたCircuitBreakerオブジェクトを得ることができます。このオブジェクトによってチャネルゲートウェイに合わせてカスタマイズできるようになっているので、簡単に適用することができました。 CircuitBreakerのアノテーションの使用 talk-channel-gatewayソースコードにおいてCircuitBreakerは、@CircuitBreakableアノテーションを使用して適用できます。 @CircuitBreakable(CircuitBreakerGroup.HBASE_CLIENT_USER_SETTINGS) public ChannelSettings findBy(String mid) { ... } 上記のように適用した場合、findBy()メソッドが呼び出される度に成功/失敗を監視し、その結果によってCircuitBreakerが開閉します。HBASE_CLIENT_USER_SETTINGSはCircuitBreakerで束ねるグループを指定するもので、各メソッドの失敗率を計算する際もグループ全体の呼び出し回数に対する失敗回数で計算し、CircuitBreakerの開閉時も一緒に開閉します。 CircuitBreakerの設定は、CircuitBreakerGroupというenumオブジェクトで次のように設定できます。 public enum CircuitBreakerGroup implements ExceptionFilter { SAMPLE_DEFAULT { }, SAMPLE_API { @Override protected ExceptionFilter exceptionFilter() { return cause -> !(cause instanceof AuthenticationException || cause instanceof ApiPermissionException || cause instanceof ImproperRequestException); } }, HBASE_CLIENT_CHANNEL_MATRIX { }, HBASE_CLIENT_USER_SETTINGS { }; protected ExceptionFilter exceptionFilter() { return cause -> true; } public CircuitBreaker circuitBreaker(CircuitBreakerListener listener) { return new `CircuitBreakerBuilder`(name()).exceptionFilter(exceptionFilter()) .listener(listener) .build(); } @Override public boolean shouldDealWith(Throwable throwable) throws Exception { return exceptionFilter().shouldDealWith(throwable); } } チャネルゲートウェイではExceptionFilterをカスタマイズして使用しました。それ以外のオプションは、Armeriaのデフォルトオプションをそのまま使用しました。もし、他のオプションを変更して使いたい場合は、circuitBreaker()メソッドを修正して使用できるでしょう。 Armeriaでは、どんなものであってもExceptionが発生した場合は基本的に失敗とみなすようになっています。しかし、チャネルゲートウェイでは、権限がない場合などをExceptionとして処理して返すので、それを区分する必要がありました。そのため、ExceptionFilterをカスタマイズして使用しました。そして、CircuitBreakerのステータスが変わる度にログを蓄積できるように、チャネルゲートウェイのためのListenerも追加しました。 アノテーションに適用するグループはenumオブジェクトで指定でき、enumオブジェクトを実装部においてグループごとに設定を変えられるようにしました。 CircuitBreakerにおけるproceed()の実装 Aspect オブジェクトのproceed()コードは以下のとおりです。 public class CircuitBreakerAspect implements Ordered { private final Map<CircuitBreakerGroup, CircuitBreaker> circuitBreakers = new (…)
↧
↧
LINE DEVELOPER DAY 2016 公式サイトと応募フォームを公開しました
LINE DEVELOPER DAY 2016 開催のお知らせで開催告知をさせていただきましたが、公式サイトと応募フォームが公開となりましたのでお知らせいたします。 English 開催概要 開催日時 9月29日(木) 10時開場、18時半終了予定 場所 渋谷ヒカリエ9F ヒカリエホール 参加費 無料 懇親会 イベント終了後、同じ会場で開催予定です 対象 アプリやWebなどの開発に関わるエンジニア 応募方法 こちらの応募フォームからご応募ください 応募締切は9月15日(木)です 一般プレス枠は先着50名、一般参加枠 450名となっております。一般プレス参加はご自身でブログや各種メディアで定期的に記事を書いている方が対象となり、イベントについて何かしら記事をあげていただける場合のみ選択してください。一般参加枠が抽選となった場合は当落結果を9月22(木)を目処にメールにてご連絡する予定です。(抽選にならなかった場合も必ずメールはお送りいたします) タイムテーブル LINE DEVELOPER DAY 2016 公式サイトにてご確認ください 懇親会 同じ会場にて行います、参加費は無料です Twitter 公式ハッシュタグ #linedevday 皆さまのご応募をお待ちしております。 作成者の紹介 Kushii: Developer Day 2016の運営を統括しています。LINEがもつ技術を社内外により楽しく、よりexcitingにお伝えするべく奮闘しています。
↧
内部データパイプラインへのKafka Streamsの適用
Kafka Streamsのご紹介 こんにちは。LINEでサーバ開発エンジニアとして働いているYuto Kawamuraです。主にHBase、KafkaといったLINEの中核的なストレージを開発・運営しています。 昨年下期からは、IMF(Internal Message FlowまたはFund)と呼ばれる新規プロジェクトも担当しています。このIMFプロジェクトの目的は大きく2つあります。 内部システム間のevent deliveryを統一された方法で行うデータパイプラインの開発 LINEサーバシステムにおけるバックグラウンド処理を担当するコンポーネントの一つであるtalk-dispatcherの置き換え この2つの目的は互いに関連性がないようにみえますが、これらの目的を達成するために、Apache Kafkaとストリームプロセッシング技術を適用することを考えています。Apache Kafkaは、LinkedInによって開発され、使われてきた大容量の分散メッセージングシステムです。ユニークな機能を多数提供していますが、一番重要な特徴は次のとおりです。 ディスクベースの永続化を提供すると同時に、ページキャッシュを活用してインメモリに引けをとらない高いスループットを実現しています。 複数のconsumerが一つのtopic(queueのような概念)から複数回メッセージを取得できます。このようなやり方が可能なのは、クライアントがそのqueueからどこまでデータを取得したか、その位置を知らせてくれる「offset」を管理しているためです。 Kafkaエンジニアリングの基本やIMFプロジェクトのコンセプトアイデアなど、面白いテーマはたくさんありますが、今回はストリームプロセッシングの実装方法にフォーカスしてご紹介します。 ストリームプロセッシングフレームワーク ストリームプロセッシングには、Apache Storm、Apache Spark、Apache Flink、Apache Samzaなど広く使われているフレームワークが複数あります。ここで、最初に採用したのはApache Smazaでした。 SamzaはKafkaと同様、LinkedInで開発されました。Kafkaと連携するように設計されているため、Kafkaとの統合に標準対応しています。基本的にはよく動作しましたが、サービスに直接的に影響を与え得るコアインフラを構築することを考えると、いくつかの懸念点がありました。 SamzaはYARNと連携するように設計されています。YARNはとてもうまく作られている分散リソース割当フレームワークであり、広く使われていますが、今回の使途には適さないと考えれらるいくつかの点がありました。 当初バッチ処理のために設計されたものであり、ストリームプロセッシングは可能ではありますが、Hadoopを継承した一部の部分がストリームプロセッシングに適していないと感じました。 LINEのデプロイシステムであるPMC(Project Management Console. LINEの主要サービスを管理するために使用するツール。CMDB(configuration management database)のビルド機能と配布機能を合わせたサービス)との親和性がありません。 全体のアーキテクチャをシンプルに保つことを意識した上で、今回のケースにおいてはYARNの主要な機能であるリソースのアイソレーションや割り当てといった機能は必要ありませんでした。その理由は次のとおりです。 サーバは、基本的にサービスごとに別途割り当てられます。 物理メモリを消費するのはほとんどがheapですが、JVMはheapサイズの上限を制限するオプションを持っています。 アプリケーションの特性上、CPUは問題になりません。 ネットワーク問題があることは想定されますが、YARNにはネットワークI/Oを制限する機能がありません。 社内のエンジニアリング設備は、「host」の概念に徹底的に従っています。例えば、サービスのモニタリングに使用する独自開発ツールであるIMONは、hostごとのメトリクスを確認したりアラームを送信したりすることができ、Kibanaはhostごとのログを保存します。そのため、jobを実行するhostの決定をYARNに任せるには、さらなる作業が必要でした。 Apache SamzaのDevelopment activityはあまり活発ではないように見えました。 言うまでもなく、YARNはリソースプール上で多くのjobを実行するためには有効です。現在、統計用jobや調査用に実行されるアドホックなjobの実行に用いられています。 Kafka Streams 2016年3月10日、Confluent社(LinkedInでApache Kafkaを開発した人々が設立した会社)が、 「Introducing Kafka Streams: Stream Processing Made Simple」というタイトルのブログ記事を投稿しました。この記事を読んで、Kafka Streamsは我々が求めていたものに限りなく近いと思いました(この記事を読むまでは、独自の実装を開発しようかとも思っていました)。他の一般的なストリームプロセッシングフレームワークが「実行フレームワーク」であるのに対し、Kafka Streamsは「ライブラリ」です。Apache Samzaから継承した概念も一部ありますが、重要な差があります。 ただのライブラリであり、実行フレームワークではないため、ユーザーが手動で実行させる必要があります。特定のフレームワーク上で実行するか、またはpublic static void main()を使うかは、開発者に委ねられています。 Kafkaのプリミティブな機能を活用し、コア機能を最小のコードでシンプルに実装しています。 シンプルなDSLを使用してプロセッシングトポロジーを定義できます。 Kafkaのコミュニティが開発をしているので、非常に活発な開発活動を期待できます。 Rolling restartに対応しています。この特徴は、単一のインスタンスのみをアップデートした上で、プロダクションのトラフィックを受けながら動作確認するためにも便利です。 Kafka Streamsは、Kafkaバージョン0.10.0で公開されました。私たちが初めてKafka Streamsを試してみたのはまだリリース前のときだったので、ソースリポジトリから自前でartifactをビルドする必要がありました。なお、Kafka Streamsは、バージョン0.10.0.0以上のKafka brokerを必要としますが、現在使用しているクラスターのバージョンは0.9.0.1です。従って、互換性のないプロトコルをダウングレードするために、クライアントライブラリを手動でパッチするなどの多少筋が悪い作業が必要でした(もちろん、新しいバージョンがリリースされる次第、クラスターをアップグレードする予定です)。それでも、新たに実装を自前で作るよりは簡単な作業だっだと考えています。 次は、Kafka Streamsが提供する特徴的な機能について説明します。 Masterless Kafka Streamsは、障害検知、処理ノード間のコーディネーション、パーティションの割り当てなどを行うために通常の分散システムに存在するマスターという概念がありません。その代わり、Kafka独自のコーディネーションメカニズムに全面的に依存しています。つまり、worker間の直接的な通信はありません。KafkaStreamsのインスタンスを作成すると、与えられたapplicationIdに対するconsumerの一つとして、Kafka brokerにsubscribeします。リバランスが必要な場合、またはfailoverが発生した場合は、Kafkaのbrokerがそれを検知して処理するため、worker間の通信は不要です。 High-level-DSL APIとLow-level API Kafka Streamsは、ストリームプロセッシングのプログラミングのためにHigh-level-DSLとLow-level APIの2つのAPIに対応しています。 High-level-DSL 多くの場合、ストリームプロセッシングは、ストリームにtransform、filter、join、aggregateなどの処理を適用し、その結果を保存するといった流れになります。このように基本的な演算処理を行うには、High-level-DSLインターフェースが適しています。High-level-DSLを使用すれば、Scala Collections APIとかなり類似した形でcollection、transformなどの演算をプログラミングできます。以下は、IMFプロジェクトでloopback topic replicatorを使用した例です(loop topic replicatorの用途は、特定の用途に合わせてオリジナルのtopicのメッセージをフィルタリングし、新しいtopicに保存することです)。 KStreamBuilder builder = new KStreamBuilder(); KStream<Long, OperationLog> stream = builder.stream(sourceTopic.keySerde(), sourceTopic.valSerde(), sourceTopic.name()); Map<String, Set<OpType>> categories = loadCategories(); for (Map.Entry<String, Set<OpType>> (…)
↧
LINE DEVELOPER DAY の雰囲気を動画でお伝えします
参加登録を受付中のLINE DEVELOPER DAY 2016 の準備を行っています!沢山の方にご来場いただけるように、昨年のイベントの様子がわかる短い動画を作成しました。是非ご覧ください。 詳細はこちらからご確認ください。 ▼LINE DEVELOPER DAY 2016 公式サイトと応募フォームを公開しました 以上、Kushiiよりお伝えいたしました。
↧