MOV タクシー配車アプリ RubyからGolangへ刷新 マイクロサービス化

RubyからGolangへの移行を進める過程で、システムアーキテクチャがマイクロサービス化していくという稀有な体験をしたので記事を書きました。

次世代タクシー配車アプリMOV(モブ)及び、タクシー車両内の乗務員向けアプリに係る WebAPI 50前後をRailsからGolang net/http に刷新しました。その過程でマイクロサービス化が進んだ事例を紹介します。MOV サーバエンジニア池田 周平です。サービスを継続しつつシステム刷新するために、なぜその判断を行ったかについてお伝えできれば幸いです。

MOV(旧タクベル)ご存知でしょうか?神奈川、東京でサービス提供中のタップ操作でタクシー配車ができる配車アプリです。 スクリーンショット 2018-12-28 11.03.58.png

実証実験を繰り返しサービスリリースしました。 立ち上げ初期段階から居たメンバーに話を聞くとRailsで高速にプロトタイピングを繰り返していたそうです。 リリース直前にGAE FEサーバのスケールとスピンアップ速度の観点でGAE SE Golangへ刷新を決め、新設WebAPIはGolangで実装しましたが大部分はRailsのままリリース当日を迎えました。

スクリーンショット 2019-01-08 19.19.41.png

APIバージョンをv1, v2, v3と上げ、アプリの強制バージョンアップでRubyからGolangに切り替える作戦を立てるも、後方互換性を維持し古いアプリでも配車可能であり続けるという運用方針があり、コード2重メンテ問題を回避するため断念しました。開発チームではGolang刷新を完遂したいとたまに話題にしつつも、日々の機能追加や運用に工数を割いていました。

GAE 1%カナリアリリース

リリース直後特有の繁忙期が過ぎたある日、マネージャからGolang移行チーム設立と担当を任されました。移行チームが出来て任されると自分ごとになりムクムクとやる気が出てくる点ワタシ自身が驚きました。

まず最初に考えたことは安全に移行するための仕組みです。

車両軌跡データやユーザアプリと乗務員アプリ間で配車ステート更新を行うため一部のデータ構造や通信シーケンスが複雑です。開発環境でバグ取りきれず本番環境で不具合に繋がる可能性がどうしてもありました。電車やタクシー内で考えた結論はカナリアリリースの仕組みを作り WebAPIごとに最初の24時間はRuby99%, Golang1%でトラフィックを分割して監視、その後割合を増やしていくという作戦でした。

GAEはservice versionごとの段階的なトラフィック切り替えをサポートしていますが、ルーティングを制御するdispatch.yamlの更新はゼロイチ切り替えのためproxyサーバを用意して切り替えることにしました。

GAE標準のトラフィック切り替え機能

スクリーンショット 2018-12-28 13.20.36.png

Golang移行対象WebAPIの1%カナリアリリース

Proxyのversion1と2の差は、刷新対象のWebAPIについてトラフィック流し先がRuby版かGolang版であるかの違いです。 スクリーンショット 2018-12-28 13.47.20.png

このようなアーキテクチャ設計にした狙いは、ゼロイチでルーティングを切り替えるGAE disptach.yamlの仕組みから最小工数でカナリアリリースできるように変更できる点、RubyとGolangサービスで共通formatのログを出力できる点です。1手で2つのメリットあるため採用しました。Cloud Functionsを利用するといった他の選択肢もありました。複数ある選択肢から早期に絞りこめたのはGoogleテックコンサルの皆様に定期的に相談できる恵まれた環境にあった点が大きかったです。サポートとても感謝しています。

Proxyサーバを実装する

GAE dispatch.yamlを代替するサービスを便宜上proxyサーバと呼んでいます。実態はHTTPサーバでHTTP CONNECT methodはログ出力するため利用していません。次のようなざっくり目標と設計で開発しました。

  • Proxyは通信の土管に徹するサービス
  • 処理のオーバーヘッドは50ms以下が目標
  • APIサービスへのHTTP通信はNon-blocking I/Oで必ず行う
  • JSONパースは処理時間が掛かるため行わない
  • BigQueryへログ出力を行う

Golangで素直に書いていけば実現する仕様です。本体は200行くらいでどのサービスに通信を振り分けるかはrouterをそのまま利用して実装します。仮想コードの方が伝わるので載せておきます。


func init() {
    router := router.New()
    setAction(router, "/", iamproxy)
    setAction(router, "/v1/drivers/*path", rubyService)
    setAction(router, "/v1/users/*path", golangService)
    http.Handle("/", router)
}

func main() {}

先ほど本番サーバをStackdriver traceで計測したらproxyの処理時間は15msでした。サービス間の通信はurlfetchを利用していて、GAEだとGCPの同一データセンター内にdeployされる特性があるためレイテンシは低めです。詳細は公式の Google App Engine 上でのマイクロサービス アーキテクチャ に記載があります。

routerはwild card routingといった標準的な機能が利用できるものを採用しました。特に高速化のために内部で Radix tree を生成し、サーバ起動時にURL routingの名前空間が重複しているとエラー吐いてどこが重複したか教えてくれるようならライブラリを利用するとよいです。複数のAPIを段階的に移行する際の助けになりました。

Proxy導入でログ出力を強化する

複雑な構造を持つJSONをRubyからGolangに移行したとき、RubyとGolangの細かな仕様差、たとえばゼロ値で苦しめられます。 元の構造では気軽nullを扱っておりJSON objectの各プロパティの型がnullableになっていました。ArrayやStringが空のとき [] or "" or null がAPIごとにバラバラだったため、正しく移植しきれず何箇所かで失敗することが予想できました。

現行WebAPIがどういった構造のJSONを送受信しているか蓄積し知るためProxyサーバで HTTP Request/Response/Headerを全てStackdriverにログ出力して、Stackdriver exportでBigQueryにsyncしました。この設定はボタンポチポチで設定できる割に効果が大きく移行をサポートする強力なツールになりました。(開発者用のログはオートモーティブ事業部内での厳しい個人情報取扱規程・個人情報保護指針があり、位置情報や選択内容及びアカウント情報は全てサーバ内部のメモリ上で削除し個人を特定出来ない形でログ送信しています)

億単位の通信ログからBigQueryで目当てのログを検索できたときは、1歩時代が進んだ感あって気に入っています。またStackdriverはStackdriverMonitoringで簡単に監視設定を作り込みSlackやPagerDutyと連携できるため頻度高く利用しています。

機能追加とGolang移行のバランス

サービスへの機能追加とシステム刷新のバランスは難しい問題です。開発の手を止めることが出来ればよいのですが、システム刷新を理由にリリース直後のアプリで機能追加速度を落としたくはありませんでした。50前後あったWebAPI次の5つに分類し段階ごとにリリースしました。特にHTTP GETなWebAPIはステートレスでテスト容易だったため早期に移行を行いました。5段に分けてリリースした理由は、1段目は単純なAPIを移行し実行可能性を調査するため、2段目移行は移行対象が大きすぎて全体把握と品質担保が難しいといった問題を回避するために、QAを行いやすい単位で分割していきました。

  • アカウントAPI
  • 配車API(method:GET)
  • 配車正常系API
  • 配車準正常系・異常系API
  • その他(お知らせ等)

移行中のGoとRubyどちらに実装すればいいといったコンフリクトが複数発生するなと予期していました。実際はごく少数しか発生せずスムースに移行完了でき、きっと私が気づかない所で開発チームメンバーが配慮・調整してくださっていたんだと思います。

振り返るとシステム刷新する上で開発チーム全体への影響を最小にするポイントはいかに早く刷新コードをmasterブランチへマージするかという点です。Proxyサーバでトラフィックを切り替えない限り蓋ができる構造だったため、完成次第masterブランチに投入して本番リリースを行いました。蓋を開けるタイミングはQA完了後です。早い段階で刷新したコードが他の開発者の目に触れる場所に設置できた点はとても良かったです。

マイクロサービス化と開発組織

現在アプリから見えるサーバは次のような構成になっていて9名の開発者で開発しています。(これ以外にもFleet Management System, タクシー事業者向け管理サービス, CS対応向け管理サービスとその開発チームありますが図からは省略しています)定めたというより自然とこのような形に落ち着きました。言語化すると次の基準です。現在のスナップショットでしかないため人員が増えるとルールは変化していきそうです。ポイントはサーバ間認証のサービスを増やしていっている点で部品としてふるまうためマイクロサービス化の副作用少なくメリットを享受できると考えています。

  • API Service本体は全員が開発
  • 各マイクロサービスは2名前後で開発
  • user/driverのaccess tokenを認証認可するサービスはAPIに集約する
  • MOV以外でも利用需要がありそうな機能はサーバ間認証でマイクロサービス化

スクリーンショット 2018-12-29 15.13.53.png

GEOはgeographyの略で一緒に開発していたエンジニアがすごい勢いで空間参照系について詳しくなり、いつの間にか作り終わっていた機能です。代表的な機能はユーザや車両がどの営業区域にいるか経度緯度情報からの地域判定です。PostGIS DBのCPUで判定計算している点が特徴です。

E2Eテストを書く

proxyを対象にE2Eテストを書きました。テストケースは本番の配車履歴から頻出パターンを抽出しました。検査項目はHTTP ResponseのJSON SchemaチェックとRDBのレコード状態の確認です。RSpecの生産性の高さと、使い捨て前提の割り切りでサクサク書け手動で再現するには2時間くらい掛かる分量になりました。捨てるにはもったいない出来だったのでbotに組み込みQA環境を自動試験しています。

スクリーンショット 2018-12-29 16.43.36.png

まとめ

振り返るとRubyからGolangへの移行を進める過程で、システムアーキテクチャがマイクロサービス化していくという稀有な体験ができしました。短期間で大きなトラブルなく安全に移行完了できたのはカナリアリリース、ログ基盤、E2Eテストと足回りを強化したあと移行を行った点にあると思います。

このアーキテクチャは現在のスナップショットであって、今後開発リストにあまたある新規開発を行っていく上で変化していくでしょう。チーム内では配車サービスを独立といった話をしています。

お話変わってDeNAでは年に1度TechConを開催しています。今回移行作業を強力にサポートしてくださった惠良 和隆さんの発表もあります。ぜひ。 https://techcon.dena.com/2019/

最後まで読んで頂きましてありがとうございます。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

QA Night #1 開催レポート(第二部)

はじめに

品質管理部の河野です。 開催レポートが遅くなってしまってしまったのですが、「おわりに」で遅くなった言い訳を書かせて頂きます。
すでに第一部の松尾谷さんの講演はこちらでレポートさせて頂きました。
こちらの第二部では、DeNAパートの中でも事例のところにフォーカスを当ててレポートいたします。 今回、DeNA QA の事例として、テストプロセス標準化の取り組みを発表させて頂きました。以降、発表の背景と概要をレポートいたします。

発表の背景

ちょうど1年前の12月くらいから部門横断の改善活動を開始したのですが、そのとき真っ先に着手したのがテストプロセスの標準化でした。各チームでバラバラだったテストの進め方をまずは全体的に共通化しようと言うのが本発表の取り組みです。
その後、標準テストプロセスが概ね出来上がった段階でその導入を進めつつ、TPI NEXTを使ったテストプロセスのアセスメントや標準テスト観点の整備などの取り組みを進めてきました。また、テストプロセスが標準化されたことで、今後はテスト活動のメトリクスの収集を行っていく予定です。
ということで、まずはテストプロセスを標準化していくことで、その後の活動がスムーズに進んだように思います。 それでは、当日の発表概要に移ります。その前に、当日のスライドはこちらになります。

DeNA QA Night #1 DeNA part from Tetsuya Kouno

発表の概要

当日の発表では、上記のような背景を初段に説明して、その後は、具体的にどのようにテストプロセスを標準化していったのかという事例を紹介しました。
テストプロセスの標準化というと難易度が高そうに見えますが、我々が取ったアプローチは以下になります。
1.各チームのテストプロセスの見える化する
2.上記テストプロセスの共通化する(積の共通とする)
3.成果物や処理の名称を決める
それで、当日は1.の見える化を「カレーライスを作る」演習を交えて、皆さんで少しワークをしてもらいました。思いの外、盛り上がってよかったです。
その後は、2.と3.を具体例を交えながら解説していき、最後の方で標準化のメリットなどを示しました。

後日談1:プロセスに関しての松尾谷さんの発表について

松尾谷さんの発表で、品質関連のアプローチとして「プロセスや技法」は負け犬の遠吠え、
のような解説がありました。 それに関して、後日というよりは発表後の話になるんですが、
松尾谷さんから以下のような意図のコメントを頂きました。

私が言ったのは河野さんの発表のようなプロセスではなくて
スタッフ部門や管理部門が押し付ける規範的なプロセスを指しているので
逆にこのようなプロセスを標準化するのは良いことだ

ということで、今回の取り組みはそれほどずれていなかったようで安心しました。
今回、気をつけたのは、ボトムアップのアプローチで進めたのでやはりそれが良かったと思いました。

後日談2:PFDってそんなに簡単なだっけ?

本イベントに参加した私の知り合いに、とあるイベントであったのですが、こんなことを言われました。

PFDでプロセスを書くのを簡単に発表してたけど、
そもそも目の前の業務をPFDに書くことは結構難易度高いんじゃない

はい、おっしゃる通りで、よく見かけるのはフローチャートになっていたり、
成果物と処理がごっちゃになったりして、PFDで表現するのは結構難しです。
それで、私は以下のような工夫をしております。

  • 最終成果物から戻るようにプロセスを書いていく
     最終成果物からその前の処理、その処理の入力成果物といった感じで考えるほうが
     経験的に知的ハードルが低くなるように感じます
  • 最初はメタに捉えて、作業の粒度を荒くする
     細かく考えるとキリがないです。まずはメタに捉えて、細かくしていきましょう。
     細かくしていくところは参考資料を見てみてください。
  • ホワイトボード / 紙と鉛筆で書く
     いきなりpptで清書すると挫折します。挫折というより、時間切れになると思います。
     なので、まずはラフにスケッチしましょう。
     スケッチできなければ、よくわかっていないことなので、次の工夫です。
  • 一人で考えすぎずに、他の人を巻き込む
     実態がわからなくて、PFDで表現できないところが出てきます。
     なので、そういうところは知っている人に聞くのが早いです。
  • 成果物と処理の名前付けに気をつける
     これは重要です。周りのメンバが共感できるような実態にあった名前をつけましょう。
     それと、成果物と処理にふさわしい名前、特に処理は動作を表す名前をつけましょう。

おわりに

今回の第一回、DeNA QA Night は参加者・講演者の皆さんのおかげで成功だったと思います。ただ、これは終わりではなくて始まりです。
次回もやります。日程は3月6日(水)で決まっております。次回も業界の一線級の識者にお声がけしてます。是非、期待して下さい。
ということで、次回日程が決まってから開催レポートを書きたいと思っておりましてこんな遅い開催レポートとなってしまいました。という、言い訳でした。
皆様、良いお年を!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

ここでしか見られない DeNA TechCon 2019 のセッション4つ

og.png

DeNA の様々な技術的なチャレンジをみて参加者のみなさんに「面白かったー」と思ってもらいたい DeNA TechCon。こちら次回開催は 2019年2月6日(水) で、登壇情報もほぼ全て出揃いました!(ゲストセッション、LTセッションなどはまた後日お知らせします!)

DeNA グループ全社で取り組んでいる様々な取り組みの中から厳選した21セッションをお届けするので、本当に全部おすすめ。そんな21セッションの中から、社外では発表する機会が少なかったり、DeNA TechCon だからこそ話せるような、他の技術系イベントでは見ることが難しいと思われるセッションを各トラックから1つずつご紹介します。

「AI 技術の事業への応用」トラック

パネルディスカッション:データサイエンスの競技者、Kagglerたちが活躍する職場とは

2018年8月末、DeNAのKagglerである小野寺和樹と加納龍一を含むチームが、過去最大のKaggleコンペである"Home Credit Default Risk"にて、7198チーム(参加者数8572名)中2位に入賞しました。

彼らを含め、DeNA では データサイエンス競技「Kaggle」のトッププレイヤーが集まっています。この Kaggler たちは一見すると事業貢献からは遠い競技者だと見えてしまいますが、 彼らと連携するメンバーの協力もあり、Kaggler たちは事業でも大活躍しています!

Kaggler とはどういった人たちでどのように事業でも成果をだしているのか、「Kaggler たち自身の立場」、「彼らと連携するメンバーの立場」の両面から話を聞ける機会は少ないと思います。そのためおすすめのセッションです!

参考記事

「クラウド活用」トラック

DeNAのインフラ戦略 〜クラウドジャーニーの舞台裏〜(仮)

現在約 3,000 台のオンプレミスのサーバーを運用している DeNA は、3年かけてオンプレミスで運用する全てのシステム基盤を全面的にクラウドに移行することを決定しました。
その決定にいたるまでの裏側の話は、現在オンプレミスだがクラウドに移行しようか悩んでいる人や、現在クラウドを使っているが低コストと安定運用を両立したい人にとって、とても参考になる話だと思われます。
多くの人に興味を持ってもらえるだろうこの登壇内容について、この意思決定を推進した 金子 俊一が自ら登壇してお話ししますので、是非見てもらいたいです!

参考記事

オンプレミスに強みをもつDeNAはなぜクラウド化を決めたのか?その舞台裏と今後の展望

「サービス開発」トラック

ヘルスケアサービス開発の裏側 〜品質と開発効率の両立〜

ヘルスケアは一般的なサービスに比べるとセキュリティに求められる水準が高く、どうしても開発スピードと両立させることが難しいそうです。そんなヘルスケアのサービスでセキュアな状態を維持しつつも開発スピードが高いままで - オンプレからクラウドに移行する - マイクロサービス化するという点 の2つを推進しており、様々なサービスにとって参考になる情報が盛りだくさんで、非常に見応えある内容だと思われます。当日はサーバサイドの池松、クライアントサイドの四方がそれぞれ話すので、アプリケーション開発、サービス開発に携わるエンジニアにはぜひ見ていただきたいです。

「ものづくりを支える技術」トラック

スマホゲームのチート手法とその対策

スマホゲームではさまざまなチート方法があるそうなのですが、その方法について「チート手法」と「その対策」を紹介してくれる場はあまり無いそうです。
チート方法はセキュリティエンジニアだけが知っていたら良いものではなく、アプリ開発やサービス開発するエンジニアも知っておくべき知識ですよね。セキュリティエンジニアとして知識を深めたい人、アプリ開発エンジニアだけど知識としてチート方法と対策を知っておきたい人にはぜひ見ていただきたいです。

終わりに

本当にすべてのセッションがおすすめなのですが、今回はその中でも 社外では発表する機会が少なかったり、DeNA TechCon だからこそ話せるような、他の技術系イベントでは見ることが難しいと思われるセッション 4つをご紹介しました。

また、実はまだ公開していないゲストセッションや、LTに関しては 公式 Twitter アカウントの DeNAxTech で今後ご紹介していきますので、まだフォローしていない方はぜひご登録下さい。

icon_tw@2.png
また肝心の DeNA TechCon 2019 について、まだ参加登録していない人は以下の Peatix から参加登録のほどよろしくお願いいたします!!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

LLVMを用いたチート対策ツールを作っている話

この記事はDeNA Advent Calendar 2018の24記事目です。

こんにちは、セキュリティ部セキュリティ技術グループ ツール開発チームの小竹 泰一(aka tkmru)です。 脆弱性診断業務の傍ら、ツール開発チームでは、パッチ管理ツールやチート対策、脆弱性診断のためのツール開発を行っています。 この記事では開発中のLLVMを用いたチート対策ツールの紹介をしたいと思います。

はじめに

本題に入るまえに、チートをされるとどのような問題があるのか、チートの方法やチート対策技術にはどのようなものがあるのかということを軽く説明しようと思います。

チートによるリスク

スマートフォンのゲームアプリのチートでよくあるものとしては、 「スタミナが減らないようにするもの」や、 「ステータスを不正に上昇させバトルで勝利するもの」、 「不正に課金アイテムを取得するもの」などがあります。

もし、このようなチートが横行してしまうと、適切に利用しているユーザの快適なプレイが阻害されてしまうかもしれません。 また、不正に課金を回避したり、ステータスをアップさせているユーザの存在は他のユーザの納得感を得られないでしょう。 チーターの存在はゲームバランスにも影響し、ゲームからユーザーが離れる一因となります。 ゲームアプリの脆弱性診断では、ゲームに対して実際に攻撃を行うことで、このようなチートからゲームを守ることができるかを確認しています。

チート対策技術とは

上で述べたように、チート対策はゲームの魅力を守るために重要です。 とくに、近年のゲームアプリはUX向上の為クライアント側の計算により多くのゲームロジック(スコア・ダメージの計算、勝敗判定など)を寄せています。 そのため、リバースエンジニアリングを伴う攻撃への耐性を上げることが重要なチート対策となっています。

ゲームアプリに限った話ではなく一般的に言えることですが、リバースエンジニアリングの手法は、アプリケーションを実際に動作させメモリや通信内容を解析する動的解析と、 ディスアセンブラやデコンパイラにかけた結果を解析する静的解析の2つに分類されます。 ARMアセンブリのコードを読む必要のある静的解析は動的解析に比べ、難易度が高いですが、 用いられている暗号方式などの詳細な解析結果を得るには行う必要があります。

ゲームアプリのチート対策では、この2つに対して対策する必要があります。 ここではひとつひとつを詳細に説明することはしませんが、チート対策技術には以下のようなものがあります。

  • 通信の暗号化
  • Root化端末、JailBreak端末の検知
  • VMの検知
  • デバッガ検知
  • メモリ上のデータの暗号化
  • パッキング
  • コード改ざんの検知
  • 難読化
  • ... etc

紹介するLLVMを用いたチート対策ツールでは、コードの処理の流れを追いにくくする難読化と、 パッチを当てられたことを検知するコード改ざん検知を担っています。 コードの改ざんを検知した後にやることとしては、アプリを強制的に終了させることや、ログをサーバーに送信することが考えられます。

LLVMとコンパイラ

LLVMは、コンパイラ開発のためのオープンソースの基盤ソフトウェアです。 主な特徴として、コンパイルに必要な機能がモジュール化され,各機能を統合するドライバで構成されており、拡張性、移植性に優れていることが挙げられます。

コンパイラの設計手法の一つにフロントエンド、optimizer、バックエンドの3つの構成要素に分割して設計するThree-Phase Designがあります。 LLVMを用いてThree-Phase Designを採用してコンパイラを設計すると、 内部構造は以下の画像(The Architecture of Open Source Applications: LLVMより引用)のようになります。

LLVMCompiler1.png

フロントエンドがプログラムのソースコードをLLVM IRという中間表現に変換し、 LLVM optimizerがLLVM IRのコードに対して最適化をかけます。 そして最後にLLVMバックエンドがLLVM IRのコードからターゲットのアーキテクチャのアセンブリコードを生成し、 実行可能ファイルを生成する流れになっています。

コンパイラ開発にLLVMを利用すると、中間表現をLLVM IRに統一することができ、 異なるアーキテクチャ向け、異なる言語向けのコンパイルであっても最適化部分を共通化できます。 しかも、その最適化機構はPassとしてLLVMが提供してくれています。 また、バックエンドを置き換えるだけで異なるアーキテクチャに対応できたり、フロントエンドを置き換えるだけで異なるプログラミング言語に対応できたりもします。 このようにLLVMを利用することで、1からコンパイラを作成するより効率よくコンパイラを作成することができます。

LLVM IR

LLVM IRについてもう少しくわしく見ていきましょう。 LLVM内部で用いられる中間表現であるLLVM IRは、 アセンブリ言語に似た表現で、表現力や拡張性、軽量であることを追求して作られています。 基本的な命令による操作の組み合わせで、 様々な高級言語に対応した簡潔な表現が可能になっています。 また、LLVM IRのレジスタは数に制限が無く、値の代入が一箇所でしか行えないSSA(Static Single Assignment)形式になっており、 これを用いて柔軟に変数を表現することができます。 LLVM IRには様々な種類の型が存在し、レジスタに型が対応しており、 細分化された型は高度な最適化を可能にします。 例えば、32bit整数型を表すi32型や、 128bit浮動小数点数型を表すfp128型などがあります。 これらの基本となる型と組み合わせて、構造体、配列、ベクトルといった 派生型を構成することができます。

実際にLLVM IRのコードを見てみましょう。 以下のような西暦を出力するだけのコードをLLVM IRに変換します。もうそろそろ2019年ですね。

#include <stdio.h>

int main(){
  int year = 2018;
  printf("%d", year+1);
  return 0;
}

clangに-S-emit-llvmの2つのオプションを指定するとLLVM IRコードが出力されます。

$ clang new-year.c -S -emit-llvm
$ cat new-year.ll
; ModuleID = 'new-year.c'
source_filename = "new-year.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.13.0"

@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1

; Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 2018, i32* %2, align 4
  %3 = load i32, i32* %2, align 4
  %4 = add nsw i32 %3, 1
  %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 %4)
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { noinline nounwind optnone ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{!"Apple LLVM version 9.1.0 (clang-902.0.39.2)"}

レジスタが%数値で表されているのが特徴的ですね。 アセンブリとは違い、アドレスの概念がないので操作しやすそうなのが分かると思います。

Three-Phase Designについて説明をした際、異なるアーキテクチャに対して最適化部分を共通化できると述べましたが、それ以外にも LLVM IRを用いることで対象のソースや機械語に手を加えることなく、最適化を行うことができるというメリットがあります。

LLVMをなぜ使うのか

LLVM IRを最適化に使うと便利だということを述べましたが、これは難読化やコード改ざん検知機能を実装するのにも同じことが言え、 LLVM IRを用いることで対象のソースや機械語に手を加えることなく、出力されるバイナリに難読化やコード改ざん検知機能を施すことができます。 また、現在スマートフォンで用いられているCPUはARMが主流ですが、異なるアーキテクチャのCPUを用いたスマートフォンが出てきたときの対応も容易になります。 LLVMを使って難読化に行うこと自体は、新しい手法ではなく、OSSの実装としてobfuscator-llvm/obfuscatorが知られています。

Unityで作られたゲームアプリのコードはIL2CPPを利用してC++のコードに変換することができます。 開発中のチート対策ツールでは、 この出力されたC++のコードをLLVM IRに変換し、 難読化やコード改ざん検知をいれ、 最終的にバイナリにするという方式をとっています。

難読化例

プロトタイプのチート対策ツールを使用するとCFG(Control Flow Graph)を以下のように変化させることができます。 CFGはIDA Proを使って生成しました。 これによって処理の流れが追いにくくなります。

難読化前のCFG

before_cfg.png

難読化後のCFG

after_cfg.png

今のところ、まだIDAのGraph viewでCFGを表示することができますが、最終的にはAnti-Disassemblyを施してCFGを表示できないようにする予定です。

おわりに

開発中のチート対策ツールの技術的な背景を紹介しました。 マルウェアがアンチデバッグに使っている手法などを検証しながら、 低レイヤーでの開発ができる、 このツールの開発はとてもおもしろいと思っていて、 商用ツールに負けないようなツールにしていきたいと思っています。 チート対策やLLVMを使ったツール開発の面白さが少しでも伝われば幸いです。

宣伝

DeNA TechCon 2019 を2019年2月6日(水)に開催します! ぜひご登録下さい! セキュリティに関する話もあります!! techcon2019.png

また、弊社についての技術情報は @DeNAxTech より配信しています。ぜひフォローをお願いします!!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

チーム内でJIRAを使ったペアプロ大会の企画をやった話

はじめに

これは DeNA Advent Calendar 2018 その2 の 19 日目の記事です。

はじめまして、FINAL FANTASY Record Keeper(FFRK)チームの今江です。現在は、FFRKチーム内の新機能開発チームでリードエンジニアを務めています。 FFRKは、2018年時点で4周年を迎えた長寿タイトルで、チームの規模も大きいプロジェクトとなっています。当然エンジニアの人数も多く、多数のエンジニアが日々開発を行なっています。

今回は、FFRKチーム内で行なったJIRAを使ったペアプロ大会の企画に関して紹介できればと思います。 この企画はペアプログラミングによるエンジニアの交流・成長の機会の提供や、着手されずに放置されているタスクを解決しつつ、チームの文化を醸成する目的がありました。同様の問題を抱えている方の参考になると幸いです。

JIRAとは?

JIRAとは、チケット管理型のプロジェクト管理ツールです。あらゆるタスクが「チケット」として管理され、進捗/タスク/アサイン管理など、プロジェクトの見える化に一役買っています。 FFRKチームでは、JIRAを使ったチケット駆動開発でプロジェクト開発を行なっています。

jiracon.000.png

企画の背景

FFRKチームでは、チーム内のエンジニアが集まる定例「エンジニア定例」という場があります。 エンジニア定例は普段は各チームの情報共有で終わっているのですが、せっかく定期的にやっているので、普段やらないような新しい取り組みをやったり、日頃感じているがなかなか解消できていない課題を解決したいという話題が上がっていました。

で、何かしらの取り組みをする上で、あがった要望が以下です。

  • みんな、ペアプロとかしたいって言ってる
  • JIRAが溜まっている
  • 業務とかに活きることやりたいよね
  • ゲームの改善にできるだけ工数を使いたい/繋げたい
  • チームビルディングは大事だよね。

「お、モリモリの要件やん。」ということで、しばらくネタを考えて思いついたのが、 今回紹介するチーム内のJIRAを使ったペアプロ大会 「JIRACON 2018」です。

JIRACON 2018

「JIRACON 2018」は、FFRK内の「業務効率化や既存の不具合などに関するJIRA」を題材にしたペアプロ大会です。

  • 概要
    • 1チーム3人で、JIRAをたくさんやったチームが優勝
    • どの程度「やった」かで点数がもらえて、一番点数が多かったチームが優勝
    • 出題するJIRAは、FFRK内のJIRAから適当に選出されたJIRA群
  • ルール
    • 時間: 1時間
    • チームのPC: 1台(コードを触れるPC)
    • チーム内容: リーダー1人 + メンバー2人

ざっと、こんなルールだったのですが、「やった」という基準は以下のように設定しました。

  • やったの定義
    • JIRAに調査結果を記入 1点
    • JIRAに解決策を書く 3点
    • JIRAの修正PRを作る 10点

ルールとして、何かしらJIRAに対して解決に繋がる取り組みを行うと、点数がもらえる方式を取っています。

取り組みの意図

企画の詳細を詰める中で、最終的にJIRACONの目的は以下のように整理しました。

  • 主目的
    • 互いの作業 (調査、コーディング、etc.) を見ることで、相互に良いところを吸収しあい、今後の業務に生かす
    • 今回で「JIRAをサクッと解決する」という感覚をつかみ、今後もすぐに解決できるものは溜めずに解決していく習慣づけの端緒にする
    • 限られた時間の中で調査や解決策の検討を行うことで、調査力や問題解決力の向上を図る
  • 副目的
    • 日頃触れない領域のコードに触れる
    • 溜まっているJIRAの数を少しでも減らす
    • エンジニア間の交流

この目的に沿って、JIRACONを進めるように詳細を詰めて行きました。

当日の流れ

JIRACONの当日の流れについて、説明します。

スケジュール

当日の進行スケジュールです。

  • 15:00 : ルール説明
  • 15:05 : 出題JIRAの公開
  • 15:05-15:55 コンテスト時間「50分」
  • 16:00 : 終了

※ 結果は、次回のエンジニア定例で発表

最初にルール説明を行い、またこのタイミングで再度JIRACONの目的を説明し、目的を踏まえて取り組んでもらうような流れを取っています。

jiracon.png

コンテスト中の流れ

JIRACONは、以下のような流れに沿って取り組みます。

jiracon.001.png

時間になると、JIRACONのWebページから問題一覧のページにアクセスできるようになるので、 各チームごとにJIRAを精査しJIRAに取り組みます。

SECCONなどのイメージが近かったので、専用のページをGoogle Sitesで作成しています。

jiracon.002.png

それっぽいWebページがサクッと作れたので、ちょっとしたWebページ作成におすすめです(サーバも用意する必要がない)。

全体のシステム構成としては以下のような感じです。

jiracon.003.png

(ほぼGoogleですね) あとは、採点を自動化できなかったので、ここはやむなしという感じです。

JIRAの一覧ページはこんな感じです。

jiracon.004.png

やってみてどうだったか?

最後にJIRACONを開催してみての振り返りを含めて、アンケートの結果を紹介できればと思います。 それぞれ、「取り組みの意図」で説明した3つの目的に関してのアンケートを取っています。

1. 互いの作業を見たことで、今後の業務に活かせそうか?

jiracon.005.png

一つ目の目的だった

互いの作業 (調査、コーディング、etc.) を見ることで、相互に良いところを吸収しあい、今後の業務に生かす

に関しては、綺麗に3分割されました。基本3人チームなので、役割ごとに意見が別れたようでした。 定性的なアンケートを結果を見た所、

  • 時間的な制約で、他の人の効率のいい面を見る余裕がなかった
  • 点数など競技性があったことで、個々が得点を取るための動きをしてしまっていた
  • どういうところで困っているのか/分からないのかを見れてよかった
  • 単純にスキルを吸収してもらう方へ力を入れたので、自身の得るものはなかった
  • いつも触らない領域を触って知見が広がった、業務に活きそう

傾向としては、時間的な猶予が厳しかった人、他人に吸収してもらう役回りだった人が低評価で、 競技性が合っていた人や、教えてもらう/見る側の人は目的を果たせたという結果でした。

2. JIRA解決の敷居が下がったか?

jiracon.006.png

二つ目の目的は、

今回で「JIRAをサクッと解決する」という感覚をつかみ、今後もすぐに解決できるものは溜めずに解決していく習慣づけの端緒にする

に関しては、全体的にJIRA解決の敷居は下がったという結果になりました。 代わりに、自分から能動的に動く習慣が付いたかという意識改革までには至らない結果になりました。

また、最終的に、総計 「21件」のJIRAが解決されていましたので、JIRA解決という副目的もそれなりに満たされた結果になりました。 入賞ラインのチームは、「17点、13点、12点」といずれも、修正PR 10点を1つ以上は出していました。

3. 限られた時間の中で、調査力や問題解決力の向上が感じられたか?

jiracon.007.png

最後の目的に関しては、1つ目のアンケートでも出ていましたが、時間的な制約がネックになっているという結果でした。 調査力・問題解決力が微増、全体的にポジネガが半々という状態でした。

ただ、時間に関しては「1時間では短いが、2時間だとダレそう」という意見があったので、単純に伸ばせばよかったとは言えない感じでした。

まとめ

最後に、JIRACONという取り組みをやってみた、まとめになります。

JIRAというプロジェクト管理ツールを使って、ペアプロ大会をやってみました。 互いの作業を見ながら、相互に刺激をもらえる機会を作ることができました。 また、チーム内に溜まったJIRA解決の敷居を下げつつ、ゲームの改善に繋がるような取り組みを行いました。

  • 主目的
    1. 互いの作業 (調査、コーディング、etc.) を見ることで、相互に良いところを吸収しあい、今後の業務に生かす
      • → 人の作業風景が見れてよかった or 余裕がなかった
    2. 今回で「JIRAをサクッと解決する」という感覚をつかみ、今後もすぐに解決できるものは溜めずに解決していく習慣づけの端緒にする
      • → JIRA解決の敷居は下がったが、マインド改革までには至らない
    3. 限られた時間の中で調査や解決策の検討を行うことで、調査力や問題解決力の向上を図る
      • → 一部の人には効果があったが、限られた時間だとその余裕が作りづらい
  • 副目的
    • 日頃触れない領域のコードに触れる → 人によってはあった
    • 溜まっているJIRAの数を少しでも減らす → 21件のJIRA解決
    • エンジニア間の交流 → まぁなったかなと

今後の展望

上記踏まえて、今後似た企画を行う場合のアイデアとしては、以下のようなことを考えています。

  • 時間的な制約がネックになったので、競技性のない取り組み
  • 普段関わりのある人で固めてチームを組んだので、チームを跨いだ交流の場
  • スタートから実装に取りかかれるような企画
  • 簡単なゲームを1から作る企画

JIRACONは競技性が高かったので、ゆとりを持って他人の作業を見ることに注力しやすい企画だったり、調査が必要なくやることが明確な手を動かせる企画が良いのではと考えています。

以上、FFRKチーム内で行なったJIRAを使ったペアプロ大会「JIRACON」に関して紹介してきました。 チケット駆動開発を行なっているチームがいれば参考にしていただければと思います。

jiracon.008.png

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

ISUCON8予選問題においてPerl実装で25万点を突破する方法

この記事はDeNA Advent Calendar 2018の15日目の記事です。遅刻!

こんにちは、@karupaneruraです。今日はDeNAが問題提供したISUCON8予選に関する話です。

ISUCONとは

ISUCONはIiknajini Speed Up CONtestのことで、Webアプリケーションのチューニング技術を競うコンテストです。 競技開始時刻にそれまで秘密にされていたあるアプリケーションがチームごとにサーバーごとまるっと渡されて、それを制限時間内にどこまでチューニングできるかを競います。

サーバーでは参照実装としてある仕様を満たしたアプリケーションが動いていて、その外部仕様を崩さずに(外見上)同様の挙動をするアプリケーションをそれぞれのチームがチューニングしていきます。 そして、ベンチマーカーをチームごとに実行すると仕様や整合性のチェックとパフォーマンス計測が行われて総合的にスコアとして数値化されてランキングが作れるという感じです。

参照実装は各言語の実装が提供されていて、各々の得意な言語を使うことができるほか、フルスクラッチで書き直すことも許されます。ミドルウェアの制限もないので、時間の許す限り本当に各々がベストだと思うソリューションを選択できる競技です。ぼくはWebエンジニアリング技術の総合格闘技のような競技だと思っています。

ISUCON8はどうだったか

そんなISUCONですが2018年は第8回目のISUCON8として開催されました。主催はLINEさん、サーバー提供はGMOさん(ConoHa)、問題提供はカヤックさんとDeNAで行いました。 DeNAは予選問題、カヤックさんは本戦問題という形で役割分担をした形です。

僕は予選問題の作問と模範解答(事前チューニング)を行いました。 解説記事も書いています。(おかげさまで大変好評でした)

ところで、ISUCON8では感想戦という形でチューニングの続きを行ってもらえる試みをやったのですが、その際にこの模範解答のスコアを出していました。

261421点というスコアですが、25万点オーバーを安定して出していました。 作問者なので当然に勘所はわかってるし、問題をブラッシュアップしながら並行して育てたので競技参加者の皆さんと同じ条件下のスコアではないわけですが、ここまではPerlでチューニングできるという事実を示しています。ちなみに競技中の最高スコアは10万点ほどでした。

前置きが長くなりましたが、今回の記事はこのスコアを出す構成はどのようにして作られたのかを語っていきます。

模範解答を作る目的

模範解答は、そのアプリケーションを最適化したときにベンチマーカー側に問題が起きないことの確認、攻略の際にどのボトルネックがどのように現れるのかの確認のために作成しました。(便宜上、模範解答という呼び方をしています。) これがあることで、ベンチマーカー側のレースコーディション問題の発見や問題の調整の意思決定がすばやく行えます。また、 攻略難易度が高すぎる/低すぎるの判断や、問題の調整もしやすくなります。 そのため、模範解答は早めの段階から作成していました。

模範解答を作るときに考えたこと

上記のような目的があるので、競技中に到達し得るスコアより高いスコアを出す実装にする必要があります。 そのため、実装時間は度外視して極限までチューニングすることを考えました。

極限までチューニングするにはどうするか、全体観を得たらそこから逆算して設計を考えていきます。 今回の場合は大きな難関はマイページと予約/キャンセルです。ユーザー毎にレスポンスが変わる部分があるので、ISUCON2の模範解答のアプローチのような、静的ファイルとしてすべてのデータを書き出すといった方法はとりにくいでしょう。なので、動的にレスポンスを返す形で高速化していきました。

動的に返すレスポンスを最適化するには、最終的に返したいデータモデルから逆算して必要なデータを考えていきます。最小限の手数で高速にレスポンスを作るために今回はRedisを使いました。Redisは低レイテンシーでレスポンスを返してくれて、かつメモリ消費量がMySQLと比べて少なく済む点が今回の課題では有利に働きました。

基本的な戦略は以下です:

  • キャッシュできる情報は基本的にキャッシュする
  • レスポンスはRedisのデータだけで基本的に解決できるようにする
  • 更新はRedis上のデータとMySQLを更新する
  • レポートだけデータ量の多さと整合性を顧みてMySQLを使って返す

また、構成としては最終的にアプリケーションのCPUがボトルネックになったため以下の構成を採用しました:

  • nginx - h2o - app / mysql / redis
  • h2o - app
  • h2o - app

nginxをLBとして、h2oでhttpを受けてアプリケーションへはunix domain socketでデータを送ります。

アプリケーションの実装はこちら: webapp/perl/lib/Torb/Web.pm

基本的にはこの方針と解説記事に書いたアプローチを理解できればすべての実装に説明が付きます。 ほか、細かいMySQLやRedisのチューニングやカーネルパラメータのチューニングも当然やっていますが、それらは普通のことしかやってないので今回は特に紹介しません。リポジトリにあるのでよかったら見てください。

実装は難しい部分もあるので実装の分かりにくいポイントを紹介します

GET /initialize

ベンチマーカーからベンチマーク開始時に叩かれるデータ初期化用エンドポイントですが、ここはレギュレーション上一定時間以内の処理が許されています。 そこで、初期データをキャッシュに載せてしまうことで全体の高速化を図ります。

基本的にRedisにpipelineしてクエリを投げまくるだけなのですが、ユーザー毎の最終更新イベントを作るときに課題があります。 ユーザー毎の最終更新イベントは、各ユーザーが最後に予約/キャンセルしたイベントをユニークに5件表示するという機能です。これをRedisでやる場合はSorted Setを使ってユーザーとイベントの組み毎に最終予約/キャンセル時刻を入れておく必要があります。 しかし、これを素直に解決するとユーザー数ぶんのN+1問題になってしまいます。SQL一撃で解決するためには窓関数を使う必要があります。

-- https://github.com/karupanerura/isucon8-qualify-tuned/blob/master/webapp/perl/lib/Torb/Web.pm#L249
SELECT id, user_id, event_id, updated_at FROM (SELECT user_id, event_id, id, updated_at, ROW_NUMBER() OVER (PARTITION BY user_id, event_id ORDER BY updated_at DESC) AS `rank` FROM reservations) a WHERE a.rank = 1 GROUP BY user_id, event_id

これで一発です。MySQLは8.0から窓関数をサポートしているのでこういうことができます。

また、全体売上レポートも一定のデータはキャッシュしておくことができます。終了していないイベントでまだキャンセルされてないまたは終了したイベントの最も古い予約より古い予約は、すべて終了しているイベントかキャンセルされた予約になっているはずです。そのため、そのID以前までキャッシュすることができます。

-- https://github.com/karupanerura/isucon8-qualify-tuned/blob/master/webapp/perl/lib/Torb/Web.pm#L171
SELECT MIN(r.id) FROM reservations r INNER JOIN events e ON r.event_id = e.id WHERE NOT ((e.closed_fg = 0 AND r.canceled_at IS NOT NULL) OR e.closed_fg = 1)

こういう感じで取ってきてCSVをファイルに書き出して使っておくと便利です。 この実装ではPSGIのStreaming Responseのフォーマットでレスポンスを返しているので、それを直接つかってキャッシュファイルを生成することができます。(レスポンスをそのままファイルに書き込みます)

# https://github.com/karupanerura/isucon8-qualify-tuned/blob/master/webapp/perl/lib/Torb/Web.pm#L173
my $rid = $self->dbh->select_one('SELECT MIN(r.id) FROM reservations r INNER JOIN events e ON r.event_id = e.id WHERE NOT ((e.closed_fg = 0 AND r.canceled_at IS NOT NULL) OR e.closed_fg = 1)');
my $res = $self->render_report_csv('SELECT * FROM reservations WHERE id < ? ORDER BY id ASC', $rid);
$res->finalize()->(sub {
    my $header_line = shift;
    open my $fh, '>', "/tmp/report_all_prefix_$rid.csv" or die $!;
    return Plack::Util::inline_object(
        write => sub {
            print {$fh} @_;
        },
        close => sub {
            close $fh or die $!;
        },
    );
});

ちなみに、これらの処理の過程でそこそこのメモリアロケーションが発生します。psgix.harakiri.commit を使ってプロセスごと殺してまっさらにしておくとスッキリです。

GET /admin/api/reports/sales

前の項で触れたとおりキャッシュデータを使える場合はそれをまるっと流しつつ、解説記事でも触れたとおり mysql_use_result を使ってMySQLから受け取ったデータをそのまんま流しましょう。適度にバッファリングしてwriteすると本当はもっとよいです。 なお、KossyはデフォルトでStreaming Responseをサポートしていないので、以下のようなモンキーパッチでお茶を濁しました。(忘れてなければ年末正月あたりの暇な時間にPull-Requestを投げます)

# https://github.com/karupanerura/isucon8-qualify-tuned/blob/master/webapp/perl/lib/Torb/Web.pm#L981-L1001
package Kossy::Response {
    use Scalar::Util qw/reftype/;

    sub new_with_code {
        my ($class, $code) = @_;
        bless \$code, $class;
    }

    BEGIN {
        my $super = \&finalize;
        no warnings qw/redefine/;
        *finalize = sub {
            my $self = shift;
            if (reftype $self eq 'REF') {
                return $$self;
            }

            $self->$super(@_);
        };
    };
};

まとめ

こういうアプローチでISUCON8予選問題の模範解答としては25万点オーバーを安定して出すことができました。 普段あまり使わない機能もときと場合によっては便利に使えるので、たとえば仕事で突然ISUCONになったときのためにも普段から素振りしておけると良いですね。ちなみに僕は初めて使う機能が結構ありました!(窓関数とか) ISUCONを出題するとこんな感じで色々と遊ぶことができるので楽しいです。みなさんもチャンスがあればぜひ出題にチャレンジしてみてください!

また、DeNAでは大規模なトラフィックを捌く仕事もあって楽しいです。よかったらぜひ一緒に働きましょう!

16日目はrexitorgさんです!もう読めます: GAE/Go, Firestoreでマスターデータを管理してみた件

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

自動運転技術と未来への取り組み

はじめに

オートモーティブ事業部の中西 葵です。事業部内の各プロダクト立ち上げのタイミングで様々なプロダクトにかかわらせて頂き、現在は、モビリティインテリジェント部という、オートモーティブ事業部の中でも共通的な役割を持って先端の技術に関わらせて頂いております。

先日、「自動運転技術の技術ロードマップと未来予測」というテーマで外部のイベントで登壇させて頂き、その一部をITエンジニアがオートモーティブ領域で活用している技術として抜粋してこちらの記事で共有させていただく事になりました。

ディー・エヌ・エーでは自動運転関連サービスのみならず周辺技術や有人時代から積み上げることで世の中に価値を還元したいという想いでモビリティサービス基盤を着実に構築し実績を積み上げていっております。

「自動運転業界は興味があるけど遠い世界」と感じているITエンジニアの方々にオートモーティブ事業を少しでも身近に感じて頂けましたら幸いです。

  • 自動運転技術の基礎
  • 自動運転周辺IT技術
  • 技術領域別の取り組み

の大きく3つに分けて解説させて頂きます。

自動運転サービス

自動運転というとどのようなものを想像されますでしょうか?

まず、AI、人工知能などの言葉と並び高度な技術を想像される方も多いでしょう。既に世界中の多くで語られている通り、人間同様にどこでも走れるような自動運転技術というのはまだまだ遠い未来の話ですが、限定的なエリアであれば既にサービスとしても始まっています。

国外の話になりますが、ちょうど先週発表になったのが元GoogleのWaymoが提供を開始したWaymo Oneです。利用できる場所もユーザーも限定的ですが、アプリで24時間いつでも車を呼び出して利用することが出来ます。

【参考】Introducing Waymo One, the fully self-driving service


自動運転技術の基礎

自動運転技術というと大きく「認知」「判断」「制御」に切り分けて話されることが多く、それぞれ以下の通りの内容です。

認知

ライダー、レーダー、カメラ、その他のセンサー類を用いて、車両周辺の障害物や周りの車の状況、車線、信号や歩行者等をリアルタイムで収集する技術です。各種データを用いて自己位置を推定するのもこちらに入ります。

【参考】いまさら聞けないライダー(Lidar)入門

判断

上の認知で認めたデータを元に信号が赤だったり、前方に車両がいた時に停車する。路上駐車を迂回、車線変更の判断などを行います。こちらのNVIDIAの動画が自動運転における認知、判断の処理が視覚的にわかりやすく表現されているので是非御覧ください。

【参考】NVIDIA DRIVE Autonomous Vehicle Platform


制御

判断した内容を元に車に対して実際に指示を出す部分です。自動運転車両のソフトウェアはROS(Robot Operating System)をベースに構築される事が多く、上の認知や判断を行う部分もROSのノードの一つして動作させます。

【参考】ROS (Robot Operating System)

セーフティ

基礎的な技術は上述のとおりですが、安全面では様々な課題を残したままになります。他にもセキュリティ面や、物理的にセンサーが壊れた場合にどうやってそれを補完するのか?など安全に車両を運行する上で必要なことは多数あります。 例えば古いニュースですが、有名なニュースなので記憶に残っている方も多いでしょう。走行中のジープをリモートから乗っ取ることが出来るという衝撃的な話です。

【参考】ドライバーに衝撃:走行中のジープの乗っ取りに成功


自動運転に関わる技術と言っても一言ではまとめられず様々な技術の組み合わせで道路を走行できるようになります。

自動運転の周辺技術

ここまで簡単に自動運転技術について書きましたが、DeNAではご存知の通り自動運転技術の開発は行っておりません。現時点で自動運転技術はパートナー企業様に開発をお任せしており、我々は過去20年に渡って積み上げたITの技術をどのように自動運転社会に活かしていくことが出来るのかを中心にサービスレイヤーの開発を主に行っております。

自動運転に関わるIT技術とはどのようなものでしょうか?DeNAの過去の取り組みを中心にIT技術を使って実現可能なものを見ていきましょう。「自動運転を実現するために必要な技術」であったり、「安全性を高める為に有ると良い技術」、ドライバーレスでのサービスを行う上で「必要となるであろうシステム」、そして、「有人サービスの段階でも必要」とされる技術などがあります。

ナビゲーションシステム

自動運転で車両が走行する為にまず目的地まで道路を案内する必要です。一般的なナビゲーションと同様にどの道を選んで走行するのが最適かを選択し指示します。

地図データ(道路ネットワーク)

ナビゲーションを実現するために道路情報をデータとして必要になります。道路の緯度経度や幅、制限情報などの情報を最新に保つ必要があり、それらの情報とリアルタイムな交通情報を元に現在どの道路を通るのが効率が良いかなどを判断することになります。

マップマッチング

地図データをナビゲーションに使用するためには自己位置を出来る限り正確に把握する必要があります。しかし、GPSのデータは正確ではない為、計算によって一番確率が高い場所を推定する為の技術です。 こちらのUberの動画がわかりやすいので興味が有る方は参考にしてください


高精度地図データ(3Dの空間情報)

先の地図データでは移動する範囲を大局的に見た処理になりますが、一般的に自動運転車両が走行するためには3Dの空間データを元に自己位置をより細かく車両の位置を特定する事でどのように移動するべきかという判断を行うことが出来るようになります。


信号データ

多くの自動運転車両ではカメラの映像を元に信号を判断する仕組みを開発していますが、予め信号から情報を取得することができれば、より安全に車両を運行することが出来るようになります。以下の記事のようにディー・エヌ・エーでは信号機から取得したデータを自動運転車両に送り込むような技術にも取り組んでいます

【参考】日本信号とDeNA、信号情報を自動運転車に送受信する実証実験を実施

映像のストリーミング

将来自動車がドライバーレスで運行することを想定すると、有事の際にはリアルタイムで遠隔から利用者様とコミュニケーションを取る必要が出てきます。そのために私達が検証を行っているのが5Gという高速な次世代通信技術を使った映像のストリーミングです。

【参考】NTTドコモとDeNA、自動運転車の遠隔操作を実証実験へ---5Gを使って

リモート管制システム

映像のストリーミングに限らず、リモートから全車両の位置や状態を把握する仕組みも必要になるため、こちらのような管制システムの開発も行っております。


スケジュール管理

自動運転車両に限らず、車両のスケジュールを効率的にする為のスケジューラーの開発も行っています。例えば荷物を集荷、配達順序をサービス全体として効率化することで、少ない車両台数で同じエリアを運行することが出来るようになります。

車両管理

先日東京進出を果たしたMOV(旧タクベル)では神奈川県及び東京エリアにおいて数千の車両から常に車両の状態が送られています。その車輌情報を元に、ユーザー様向けのアプリからの配車リクエストをリアルタイムで処理するようなシステムが構築されています

技術領域別

過去にオートモーティブ事業部で自動運転関連の業務で取り組んできたのは上記のようなものがありますが、高精度地図、信号データ以外は自動運転に限定した技術ではなく、幅広い領域で使われている一般的なものだと思われる方も多いでしょう。

他にも自動運転に関わらない領域で活用している様々な技術を日々活用しております。事業部全体を見渡してみると、ほとんどのプロダクトで最新の技術を駆使して開発を行っています。「大量のデータ」を「リアルタイム」で処理することを考えるとレガシーな技術ではスケールせず、私達が求めるレベルの品質でサービスを提供できないのが一つの理由です。

オートモーティブ事業領域に限らず、現在コンシューマ向けのサービスを考えるときにはモバイルアプリの開発は欠かせない技術になっています。Android, iOS, Webなどそれぞれの領域でのクライアントアプリの開発が必要になりますし、当然のようにバックエンドも必要になります。

それらを含め、技術を領域毎に分解すると以下のように分けることが出来ます。

サーバーサイド

サーバーサイドといっても幅が広すぎますが、現在オートモーティブ事業部ではAWSやGCPなどのクラウド環境を中心に利用しています。最先端の技術を積極的に取り入れるため「Google Cloud Next '18」や「AWS re:Invent 2018」 といった海外カンファレンスにも積極的に参加し技術の向上をしています。

MOV(旧タクベル)では以下の記事のようにAWSの機能を存分に活用した仕組みで運用されており、その後も進化し続けています。

【参考】タクシー配車アプリ「タクベル」を手掛けるDeNAがAWSを選択した理由

中でも特徴的で面白いのがAWS IoTです。タクシーからリアルタイムで情報を吸い上げるためにはスケールからその後のデータ処理まで考えることが多く、大量のデータを扱うことを考えるとコストもしっかりと考えていく必要があります。新しい技術をどのようにサービスに取り入れていくのかを考えるのは情報も少なく難しいことも多いですが、AWSの方とも密に連携を取りながら設計、開発を行っております。

フロントエンド

最近はスマートフォンの性能も良くなり、アプリのみならずWeb上での高いユーザビリティも求められています。そんな技術を存分に発揮できる環境です。また、様々なデバイスからのアクセスを想定した作りをしていく必要があり、レスポンシブデザインを基本としてWebサイトの開発を行っております。

【参考】【図解】レスポンシブデザインとは?定義、特徴、メリットとデメリットを解説

モバイルアプリ

アプリ開発もオートモーティブ領域においては多岐にわたります。一般的なサービス同様にGoogle Play StoreやApp Storeに提供するユーザー様向けのアプリ、自動車とつながる端末として、MOVの乗務員様向けアプリ、後部座席用タブレット向けアプリ、実証実験用にクローズドで提供する場合もあります。また実験用にアプリストアでは提供しないアプリも多数開発を行っています。念のために書いておくとiOSアプリの開発はSwiftでAndroidアプリの開発はKotlinです。

MOVではBLE Loggerというデバイスの開発を行っており、Androidアプリとタクシーメーターの連携をBLE Loggerを経由して行っています。常時接続し続け、遅延やデータの取りこぼしが発生しないような設計など、アプリストアに提供しているような一般的なアプリ開発では経験することが出来ない領域の開発も行います。

データサイエンティスト

オートモーティブ事業部では日々膨大な量のデータが蓄積し、分析されるのを待ち続けています。データ分析を待つ間にも新しい機能開発は進み、やるべきことは増え続けています。リアルタイムに24時間入り続ける交通データを元に難しい課題にチャレンジしたい方にとってはとてもエキサイティングな環境がそこにあります。

AI

DeNAでは「AI×インターネット」をキーワードに事業を広げていますが、オートモーティブ領域においても同様にAIを活用したサービスの開発を行っています。現在、力を入れているのがタクシーの需要予測になります。蓄積したデータとリアルタイムで入ってくるデータを元に需要予測を行った上でリアルタイムでナビゲーションを行うという世界を見渡しても例を見ない取り組みを行っております。こちらは私の所属するモビリティインテリジェント部を中心にAI事業部の皆様と開発を行っています。我こそはという方、興味があるので話を聞いてみたいという方、是非ご連絡お待ちしております。

まとめ

将来やってくる自動運転社会になる時に必要になるであろうサービスを有人の時代から徹底的に作り込み、ドライバーレス時代になったときにはスムーズに移行できるように長期的な視点に立ってものづくりを行っている集団がDeNAオートモーティブ事業部です。未来を作る為には大きな夢をもって難しい課題にチャレンジする必要がありますが、私達が使っている技術は特殊なものではないということを少しご理解いただけたかなと思います。新たなチャレンジを探している方、是非ご一緒に未来を創っていきましょう!

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

無線 LAN の通信品質を見える化する話

これは DeNA Advent Calendar 2018 その2 の 7 日目の記事です。

こんにちは、IT 基盤部ネットワークグループの寺増です。

ネットワークグループでは、各サービスを提供している DC ネットワークの他、DeNA グループ全体のオフィスネットワークの管理・運用も行っています。

今回は、中でも日々重要性が増している無線 LAN の特徴と、それを安定的に運用するための通信品質観測の仕組みについて、本社ヒカリエを例に紹介します。

目次

  • はじめに
    • 無線 LAN とは
    • 有線 LAN との違い
    • オフィスの無線 LAN と家庭の無線 LAN
    • オフィスの無線 LAN で発生する様々な事象
  • 無線 LAN の通信観測の仕組み
    • リスト生成
    • データ収集
    • データ集計
    • データ蓄積/可視化
  • まとめ


はじめに

1. 無線 LAN とは

無線 LAN とは、国際標準規格 IEEE802.11 で定義される無線技術を用いたローカルエリアネットワークの総称です。 1999 年策定の 802.11a/b に始まり、11g, 11n, 11ac と続き、来年からは 11ax (Wi-Fi 6) の普及も始まる予定です。


2. 有線 LAN との違い

無線 LAN は、有線 LAN と異なる以下の特徴があります。

  • 通信の伝送媒体が電波である
  • 利用には電波法による一定の制約がある
  • 接続後のスループットが動的に変化する
  • ノイズの影響を非常に強く受ける
  • 上りもしくは双方向の通信が半二重である (2018 年現在)


3. オフィスの無線 LAN と家庭の無線 LAN

オフィスの無線 LAN は、家庭の無線 LAN とは異なる以下のような特徴があります。

  • 約 15 台のアクセスポイント (以下、AP) で一つのカバーエリアを構成している
  • 1 台の AP に対して、40 - 80 台程度のステーション (端末) が同時に接続する
  • 干渉源のデバイス (Bluetooth, デザリング端末等) が多く存在する
  • 高層階では、外来波である各種レーダーの影響を受けやすい


4. オフィスの無線 LAN で発生する様々な事象

前述のような特徴から、オフィスの無線 LAN では次のような事象が発生し「遅延」や「断」に繋がります。

  • 大容量通信による通信帯域の枯渇
  • スティッキークライアントによる帯域の浪費
  • 隠れ端末・晒し端末による余分な通信待ちの発生
  • AP 同士の相互干渉による余分な通信待ちの発生
  • 遮蔽物 (パーティション等) の構成によるカバレッジホールの発生
  • レーダーによる一時的な電波の停波、ひいてはカバレッジホールの発生
  • ノイズによる SN 比の低下、ひいては通信速度の低下
  • 通信周波数の変更による一時的な通信断
  • BSS トランジション発生時の一時的な通信断
  • 無線空間上でのフレーム消失によるパケットロス
  • その他、ステーション側のドライバに起因する様々な問題

ここに挙げた例の中には、ネットワーク機器側の情報だけでは実情の確認が難しいものも多く含まれています。

状況を正確に把握し、適切な措置を行う手段として、DeNA では icmp を用いた無線 LAN の通信品質観測を行っています。


無線 LAN の通信観測の仕組み

DeNA では、社内の ESSID に接続する全てのステーションの接続状態を計測・記録しています。

この仕組みは次のスタックで構成しています。

この仕組みにより、各ステーション・AP・フロア単位の通信品質を網羅的かつヒストリカルに可視化しています。更にこのデータを監視することで、大規模な通信遅延を能動的に検知し、続く改善措置までを一連の運用として行っています。

全体構成は以下のようになっています。

itpf-networkg-wifi-01_20181204.png

各処理について順に説明します。

1. リスト生成

AP に接続しているステーションの情報は、全て上位にある無線 LAN コントローラに記録されています。このフェーズでは、その情報を元にデータ収集の対象リストを Fluentd のコンフィグとして生成します。

無線 LAN のステーションは状態が動的に変化するため、このコンフィグも一定周期で再生成・リロードしています。

ここで生成している Fluentd のコンフィグは、以下のようなテンプレートを元にしています。

<source>
  @type       exec
  command     /bin/ping -i <%= ping_param[:interval] %> <%= client[:ipAddress] %>
  keys        rtt
  tag         foobar.<%= client[:ipAddress] %>
  time_key    time
  time_format %Y-%m-%d %H:%M:%S
</source>

<filter foobar.<%= client[:ipAddress] %>>
  @type       record_modifier
  <record>
    mac          <%= client[:macAddress] %>    // ステーションの MAC アドレス
    vendor       <%= client[:vendor] %>        // MAC アドレスを保有しているベンダー名
    ip           <%= client[:ipAddress] %>     // ステーションの IP アドレス
    ssid         <%= client[:ssid] %>          // 接続している SSID 名
    ap           <%= client[:apName] %>        // 接続している AP 名
    loc          <%= client[:location] %>      // その AP を設置しているフロア名
    rssi         <%= client[:rssi] %>          // ステーションで感知している信号の減衰量 (信号強度)
    snr          <%= client[:snr] %>           // S/N 比 (信号強度と雑音強度に基づく電波品質の指針値)
    proto        <%= client[:protocol] %>      // 接続周波数帯
    user         <%= client[:userName] %>      // 接続時に利用した証明書の CN
  </record>
</filter>


2. データ収集

データ収集には Linux 標準の ping コマンドを利用しています。前項テンプレートの <source> 部分が該当箇所です。この結果を Fluentd の exec Input Plugin でパースし、RTT のみを抽出して結果値に採用しています。

Linux の ping コマンドはタイムアウトを出力しませんが、タイムアウト自体を見る必要がないため意識はしていません。これは、ping のインターバル、応答数とそれぞれの RTT が判ればタイムアウト回数も逆算出来ることが背景にあります。


3. データ集計

ソースデータが常時止めどなく流れるストリーミング系であるため、この集計処理には Norikra を採用しています。このフェーズで、ステーション毎の 1 分間のデータ件数、平均 RTT、最大 RTT を算出して、元データに付与します。

無線 LAN は移動等で RTT が変動するため、平均の算出時には Norikra::UDF::Percentile によるパーセンタイルも行っています。

本社ヒカリエには日々 2000 以上のステーション (スマホ、タブレットを含めると更に倍以上) が存在しています。それらのデータを個別に集計する仕様から、ここには多めの RAM を充当して並列で処理を行うようにしています。

ここで生成される最終的なデータは、以下のようにモデルになっています。

{
  "mac": "11:22:33:44:55:ab",                // ステーションの MAC アドレス
  "vendor": "Unknown",                       // MAC アドレスを保有しているベンダー名
  "ip": "192.168.0.1",                       // ステーションの IP アドレス
  "ssid": "ssidName",                        // 接続している SSID 名
  "ap": "AP01",                              // 接続している AP 名
  "loc": "System Campus > HIKARIE > 20F",    // その AP を設置しているフロア名
  "rssi": -43,                               // ステーションで感知している信号の減衰量 (信号強度)
  "snr": 51,                                 // S/N 比 (信号強度と雑音強度に基づく電波品質の指針値)
  "proto": "5GHz",                           // 接続周波数帯
  "user": "foo@bar.baz"                      // 接続時に利用した証明書の CN
  "count": 4,                                // 1 分間に記録されていたデータの件数
  "max_rtt": 105,                            // 1 分間に記録されていた RTT の最大値
  "min_rtt": 18.4,                           // 1 分間に記録されていた RTT の最小値
  "percentiled_rtt": 89.7,                   // パーセンタイル・カットした RTT の基準
  "avg_rtt": 45.32500000000012               // 1 分間に記録されていた RTT の平均値 (パーセンタイル後)
}


4. データ蓄積/可視化

このフェーズで、Norikra によって生成されたデータを Fluentd によって引き戻し、そこから Elasticsearch にポストしています。Fluentd から Elasticsearch へのデータの引き渡しには、Elasticsearch Output Plugin を利用しています。

これを Kibana から参照することで、各ステーション・AP・フロア単位、それぞれの通信品質を可視化を実現しています。

以下は DeNA で実際に利用している Dashboard のサンプルです。アクセシビリティ向上のため、フロントエンドは別途用意しています。

(a) フロア単位

itpf-networkg-wifi-02_20181204.png

(b) AP 単位

itpf-networkg-wifi-03_20181204.png


まとめ

以上、無線 LAN の通信品質を観測する仕組みについて簡単に紹介させて頂きました。

最後までお読み頂きありがとうございました。

DeNA では、Delight and Impact the World もさることながら、それを成し遂げる過程も非常に大事にしています。この過程の品質に磨きをかけられる手法はどんな奇抜なアイデアでも大歓迎です。

こんなアイデアあるよ! という方、是非我々と一緒に DeNA の運用業務に携わってみませんか。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

DeNA QA Night#1開催レポート(第一部)

はじめに

みなさんこんにちは。品質管理部の柏倉です。コマース系、エンタメ系サービスのQAを担当しています。 先日(2018/11/27)、DeNA QA Night#1と称してソフトウェアテスト、品質関連のイベントを開催しましたのでそのレポートをしたいと思います。 記念すべき第一回目となるDeNA QA Night#1では招待講演にデバッグ工学研究所の松尾谷徹氏をお迎えし、ご講演いただきました。それから、第二部としてDeNA品質管理部の紹介と、DeNA品質管理部が取り組んだテストプロセス標準化のお話を紹介しました。今回はその第一部、松尾谷徹氏の講演についてレポートしたいと思います。

DeNA QA Nightを発足した背景

まず初めに、そもそもなぜこのイベントを開催しようと思ったのかについてお話ししたいと思います。DeNAには品質管理部という独立した組織が存在していて、品質向上のために日々業務に取り組んでいます。オンサイトとオフサイトを合わせて、その数なんと750名!毎日750名もの人数が品質向上のために稼働しています!

しかし、これほどのパワーをかけている部門にも関わらず、その地名度は低く、DeNA社内においても「品質管理部??知らないなぁ」という人がいるほどでした。社外における知名度も同様で、DeNAに品質管理組織がある事は知られていませんでした。これはいかんという事で、社内・社外双方で知名度&プレゼンスを上げなければならない!そのための活動の一環として社外向けのQA関連イベントを主催しようという事になり、DeNA QA Nightの開催に至りました。また、イベントを通じて世の中の品質関連技術の向上に貢献したいという思いもあります。世の中の技術力向上と品質管理部のプレゼンス向上を両立すべく、今後も継続して開催していく予定ですのでみなさまのご来場を心よりお待ちしております!

DeNA QA Night_logo.jpg

心配をよそに大盛況!

品質管理部のプレゼンス向上の一環として立ち上げたDeNA QA Nightですが、そもそも品質管理部の知名度が低いのでイベントを開催したところでどれくらいのお客様にご来場いただけるのか、スタッフ一同ものすごく不安を感じながら募集を開始しました。イベントの1ヶ月前から参加希望者の募集を開始したのですが、最初はちょっと弱気で『80名くらい来てもらえたら嬉しいね』くらいの気持ちでした。ところが!公開して数日で募集人数を大きく超える応募をいただき、あっという間に応募枠が埋まってしまいました!皆様本当にありがとうございます!これに気を良くしたスタッフ一同は『あと100名くらい増やしてみようか』とか言い始めます。スタッフ一同調子に乗っちゃってるので誰も止める者はなく、勢いで本当に100名ほど枠を増やしてしまいました!結果的に、募集枠180名に対し、約260名のご応募をいただきました。まさかこんなに応募をいただけるとは思っていなかったので、本当に驚きましたし、嬉しかったです!募集枠に入りきらなかった皆様、今回はお会いできず残念ですが、是非#2でお会いできる事を楽しみにしております!

松尾谷徹氏の講演から感じた事

さてここからは、招待講演にてご講演いただいたデバッグ工学研究所の松尾谷徹氏のお話から個人的に感じた事などを書いてみようと思います。大きな印象としては、我々QA担当者にとって辛辣な問いを投げかけられているように感じました。QA担当者はこれからどうなるのか。絶滅危惧種として難民化するのか、はたまたコントリビューターとして繁栄するのか。

(以降、松尾谷氏の許可を得て講演資料から一部抜粋して画像を掲載しております。)

dena_qa_night_1_1_slide1.png

本題に入る前にQAの本質について私なりの解釈を交えて少し述べてみようと思います。講演の一節にQAの本質は測り、良否の判断ができる事とありました。この部分を私なりに解釈して説明します。従来からQAは良否の判断をするために仕様とソフトウェア動作を比較してきました。ソフトウェアの動作が仕様と異なっていれば否、合致していれば良としていたわけです。これはつまり仕様が無ければテストが出来ないという事を示しています。もし仕様に定められていない動きを見つけた場合は良否の判断が出来ないためです。そのような場合どうするかと言うと、見つけた動きを仕様とするのか、あるいはもっと良い動きに修正するのかを検討し、最終的に仕様化します。つまり、テストの実態は仕様記述だったわけです。

dena_qa_night_1_1_slide2.png

そしてここからが本題になるのですが、これからの時代は仕様記述だけのQA担当者は生き残れないと言う事をおっしゃっていたように思います。ここについても私なりの解釈を交えて少し述べてみます。QA担当者の役割が「仕様に対して良か否か」を判断する事から「社会や文化に対しての良否」を判断する事に変化してきています。また、情報サービスが主役となる時代において、情報そのものの正しさをいかに保証するかも品質における課題となっています。それから、品質に対する考え方も変化してきているように思います。テストで徹底的にバグ出しをして、不具合が出来るだけ含まれない状態でプロダクトを出荷する事に重きを置いていた時代から、OSSを用いてソフトウェア開発を進めるようになって以降は現実的で合理的な品質保証にシフトしてきているように感じます。このような時代において、仕様通りにプロダクトが作られているかを追求するだけではもはや品質は保証出来ません。では、我々QA担当者はどうすれば良いのでしょうか...

dena_qa_night_1_1_slide3.png

松尾谷氏曰く、キーワードは「Contribution」だそうです。google翻訳に聞いてみると「貢献」と教えてくれました。松尾谷氏の経験上、海外の人と一緒に働くとだいたい聞かれるのは「お前のContributionは何?」との事。世界的な流れとしてContribution(貢献)が求められるようになってきている模様です。我々QA担当者もこの流れには逆らえないと思います。難民化しないためには『Contributerである事が大切』と松尾谷氏はおっしゃっていました。講演の後、品質管理部内で解釈をすり合わせてみた結果こうなりました「規範的な批評家QAではなくて、開発やサービスにcontributionできるQAである事」。これはDeNA品質管理部と同じ方向性を示しています。その事に気が付いた時、皆とても嬉しそうにしていました。これからも我々品質管理部はサービス品質向上に向け、あらゆる面でContributionしていこうと再認識出来た講演でした!この場を借りて改めてお礼を述べさせていただきます。松尾谷様、貴重な講演ありがとうございました!

dena_qa_night_1_1_slide4.png

テストプロセス標準化のお話

DeNA QA Night#1の第二部では、DeNA品質管理部より品質管理部の紹介とテストプロセス標準化のお話をさせていただきました。この様子は追ってブログで公開します。お楽しみに!

宣伝

connpassグループへのご参加をお待ちしております!

DeNA QA Nightは主にconnpassでの応募となります。是非グループ登録をお願いします! DeNA QA Nightグループページへ

Twitterフォローお願いします!

DeNA TechCon 2019を開催します!

DeNA TechCon 2019 を2019年2月6日(水)に開催します!みなさま、ぜひご登録下さい!! techcon2019_logo.png

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る

DeNA Engineers' Blogをリニューアルしている話

@mazgiです。
これはDeNA Advent Calendar 2018の3日目の記事です。

せっかく社のBlogを書くことになったので社のBlogリニューアルについてご紹介します。 今日2018/12/03現在みえているこのBlogのリニューアルを「Engineers' Blog編集委員会(仮)」という有志の横断的な組織で進めていてだいぶ形になってきました。
(Advent Calendarには間に合いませんでした)

きっとこんな見た目になります!
we-just-building-new-dena-engineers-blog.screenshot.png

技術Blogやオウンドメディアの長期運用あるあるな話としてどなたかのご参考になればという気持ちで書かせていただきます。

なぜリニューアルするのか?

リニューアルする理由をざっと書き出すと次の3点です。

  • もっと活性化してほしい
  • 機能追加やシステム更新がつらくなってきた
  • オンプレミスでのセルフホスティングをやめたい

順にご説明します。

もっと活性化してほしい

今のこのBlogはMovable Type製なのですが、全社員にアカウントが払い出されているわけではなく、初めて記事を書くときにBlog専用アカウントを申請する運用になっています。
また書いてから公開されるまでのフローは整備されてはいるのですが当事者以外からはなかなか知ることができず、その結果新たに「Blogを書いてみようかな」と思ったときに「どうやって書くんだろう?」「どういう内容ならOKなんだろう?」「誰にレビューお願いすればいいんだろう?」といった疑問が心理的障壁になっていることがわかりました。

これを解消するため前述の「Engineers' Blog編集委員会」で「もっと気負わず思いついた時に誰でも記事を書けるようにしたい!」と話し合いました。

機能追加やシステム更新がつらくなってきた

DeNAは元々腕利きのPerl Mongerな方々が集まっていた会社でもありこのBlogのシステムは2010年頃にMovable Typeで構築されたようです。
ところでDeNAは来年2019年で20周年だそうです。IT企業として20年、すごいですね!老舗ですね!
この機会に技術Blogもシステム刷新してもいいのではないでしょうか?

前述の活性化を行うにしてもイマドキな方が色んな方に書いていただけそうですし、長く運用できそうです。
Blog編集委員会では「新し目で運用負荷低い仕組みを目指しましょう」と話し合いました。

オンプレミスでのセルフホスティングをやめたい

20世紀からWebサービスを作っておられる多くの会社がそうだと思いますが、DeNAもオンプレミスとパブリッククラウドを併用している会社です。
しかしこの度パブリッククラウドに完全移行することが決まりました :tada:
ところで2010年頃に構築されたBlogのサーバーは? ...オンプレミスです。移行しましょう!

編集委員会でも「パブリッククラウド上でサービスするのは当然としてインスタンス立てたくないね」と話し合いました。

ちなみに全社インフラのクラウド移行については弊社オウンドメディア@ITでも記事にしていただいていますのでご参照ください。
また、2019年2月のTechConでも紹介される予定ですのでこちらもぜひご参加ください。

どうやってリニューアルを進めているか?

先ほど上がった理由をブレイクダウンし、それぞれの課題を解決する方法を考えていきます。

どうやってもっと活性化しやすくするか?

まず、Blogシステムの概観をどうすれば活性化しやすいくなりそうか話し合いました。

世の中には色々な素晴らしいBlogサービスやCMSが存在することも改めて確認し、同時にエンジニアリングやデザインのリソースが少し取れそうだったので自前実装という道も生まれました。
これらの状況を加味した上で自由度とセキュリティ担保や今後の運用とを秤にかけ「薄く自前実装しよう」という方針が決まりました。

それが今の私たちにとって、システム面でも文化や雰囲気の面でも、もっともバランスの良い形に思えたのです。

まず"書きやすいシステム"にする

技術Blogの主なWriterとなるエンジニアが"書きやすいシステム"について考えた結果以下を決めました。

  • 普段使っているGitHub(Enterprise)に集約しよう
    • 記事内容はもちろん、記事執筆のフローもGitHub的にしよう
    • Pull Request -> Review && Merge -> CI/CD で記事が公開されるようにしよう
  • Markdownで書けるようにしよう
    • フォーマットの好みは色々あれどMarkdownは大抵の人が書いたことあるはず
  • 社内向けBlogを併設してもっと気軽に記事を書けるようにしよう

GitHubへの集約ですが、この画像のようなリポジトリのmasterにMarkdownで書かれた原稿がMergeされると公開されるようにしました。
(Private Repositoryですが全社員がメンバーとして設定されています)
we-just-building-new-dena-engineers-blog.0090.png

レビューは何かを開発するときと同じようにPull Request上で行えますが、Push毎にこのように記事をプレビューできる専用のURLが発行されます。
we-just-building-new-dena-engineers-blog.0050.png

このプレビュー用URLは社内から誰でも閲覧できるので例えば法務や広報といった、GitHubアカウントを持っていない方にもレビューに参加していただけます。

最後の「社内向けBlog」については、「『社名とともに世界に公開される』と考えると気後れしてしまうかもしれないけど、社内限定公開なら何書いても恥ずかしくないよね!」という気持ちで作ることにしました。

  • 「内容軽すぎない?」=>「1 tip(s)だけでも大丈夫です、社内限定公開なんで」
  • 「これ社外秘かも...」=>「社内の人が知ってて大丈夫なら書いて大丈夫です、社内限定公開なんで」
  • 「社内のあれこれ知らないと伝わらない」=>「読む人みんな知ってるので書いてください、社内限定公開なんで」

という感じで記事を書くハードル下げられるといいな!と思ってます。
社内向けBlogも公開Blogもリポジトリが異なるだけで仕組みや原稿フォーマットは一緒なので、社内限定記事を公開記事に変換する時はリポジトリ間でファイルをコピーするだけです。
社外秘な社内限定記事は後日社外秘じゃなくなるように編集して公開すればいいですし、社内知識が前提となっている社内限定記事は先に社内知識を説明する記事を公開すればいいですよね!

"書きやすい雰囲気"にする

DeNAで掲げている「DeNA Quality」の1つに「透明性」があります。
言葉通り「正直でオープンなコミュニケーション」を是とするいたって真っ当な姿勢なのですが、今回の一連のBlogリニューアルの動きとしてもこの「透明性」を強く意識しています。

リソースのほとんどはGitHubに集約され、全社員がアクセスできます。
we-just-building-new-dena-engineers-blog.0030.png

タスク一覧や進捗はGitHub Projects(カンバン)上で公開されており、自由にカードやIssueを作ることができます。
we-just-building-new-dena-engineers-blog.0040.png

SlackでのやりとりもPublic Channel上で行われ、
we-just-building-new-dena-engineers-blog.0080.png そのままでは流れ去ってしまうSlackコメントは必要に応じてGitHubのIssueコメントとして蓄積されます。
we-just-building-new-dena-engineers-blog.0081.png そしてGitHubでのコメントや色々なアクティビティはSlackのPublic Channelに通知されます。
we-just-building-new-dena-engineers-blog.0082.png

DeNAでは開発業務に従事していない方などGitHubアカウントを持っていない方もいるのですが、Slackアカウントは全員が持っているので、誰でもこれらの情報にアクセスしコメントすることができます。

こうやって記事やレビュー内容だけに留まらず経緯までオープンかつ正直に残しておくことで、今だけではなく将来にわたって「あ、こんなカジュアルでいいんだ」と感じてもらえたらいいな!と思っています。

どうやって機能追加やシステム更新を行いやすくするか?

まずどんなシステムにしてどんなサービスを使ったところで、そのままではいずれ機能追加が行えなくなり更新がつらくなると考えています。
それはきっと避けられないのでしょう。

なのでせめて2018年に考えられる継続的にアップデート可能な"オープンな普通の仕組み"を作ろうと努めました。
具体的には以下のツールやサービスを組み合わせてBlogを構成しました。

HugoとTerraformはOSSですし、その他のXaaSはどれも有名で調べればすぐに情報が得られます。
また2030年くらいまでにはBlogのリニューアルが避けられなくなるかもしれませんが、むしろもっと短いイテレーションで頻繁にシステム構成自体を再考し更新し続けられたらうれしいですね!

パブリッククラウド上でどのような構成にするか?

今からオンプレミスのサーバーを新規構築しないのは当たり前として、Blog編集委員全員に「インスタンス立てたくない!」という強い気持ちがあり、サーバーを立てない前提で話が進みました。
これだけ色々なマネージドサービスが提供されている2018年にBlogのためにサーバーを運用するリソースはもったいないですね。
そのリソースはDeNAのサービスを使ってくださっている皆さまのためにもっと違う形で使いたいものです。

構成は前述の通りなのですが、それぞれ以下のような点を考慮しました。

Markdown

平易なテキストフォーマットなので他のシステムへの載せ替えも容易。

Hugo

Apache 2ライセンスのOSSでライセンス上の検討事項が少ない。
Golang製でバイナリファイル1つで動く。バイナリさえ保持しておけば先々「本体は入手できてもライブラリが入手できない」といった事態を避けられる。

GitHub Enterprise / CircleCI Enterprise

DeNA内で標準的に利用されており世間的にもデファクトスタンダードと言える。

Terraform

MPL 2ライセンスのOSS。
Hugo同様Golang製でバイナリファイルといくつかのモジュールだけあれば動く。
IaCのとても著名なツールと言え情報も多い。

AWSの各リソース

AWS自体はいうまでもなく世界有数のクラウドサービスプロバイダで情報が大変多い。
もちろんDeNA内でも広く使われている。

Blog閲覧時のアクセス経路は、公開/社内向けそれぞれ以下の通り。

公開Blog: Browser -> CloudFront -> S3
社内向けBlog: Browser -> CloudFront -> WAF -> S3

更新時はCircleCI上でHugoにより生成されたHTML, CSS, JavaScriptなどをS3にアップロードしている。

さいごに

いちばん最初に載せさせていただいたかっこいいBlogテーマはデザイン担当の方が作ってくださいました!
(かっこいいので再掲)
we-just-building-new-dena-engineers-blog.screenshot.png

Blogリニューアルの初期は仮テーマということにして私が作ったテーマで実装してたんですけど、見比べていただけるとどれくらいかっこよくしていただいたかわかると思います(

そして残タスクはデータ移行。。
どんなシステム刷新も最後に残るのはデータ移行ですね。
完全な自動マイグレーションは難しそうなので今色々とディスカッションしてます。
we-just-building-new-dena-engineers-blog.0010.png

DeNA「Engineers' Blog編集委員会(仮)」ではこのように技術Blogのリニューアルを検討中です :muscle:
Slackでコミュニケーション取ったり、
we-just-building-new-dena-engineers-blog.0020.png 意見はフィードバックいただいたり、
we-just-building-new-dena-engineers-blog.0070.png we-just-building-new-dena-engineers-blog.0060.png オフラインで集まったり、 we-just-building-new-dena-engineers-blog.0100.jpeg

進めていますので次は「リニューアルしました!」とご報告できることを楽しみにしています。

ツイート
シェア
あとで読む
ブックマーク
送る
メールで送る