de:code 2015 レポート day1 - SPL-001 / CHK-002 / CHK-003

クロスワープの大鷲です。

前回の記事に引き続き、de:code 2015 day1 のレポートをお届けします。
個人的に day1 の目玉だと思っているセッションになります。

参加セッション

私が参加したセッションは以下の通りです。
本記事では、以下の 3 セッションのレポートをお届けします。

  • SPL-001 マイクロソフトが考える 5 年後を見据えた技術提言
  • CHK-002 クラウドアプリケーションのアーキテクチャ設計を深める
  • CHK-003 プログラミング パラダイムの知識を深める

この 3 つのセッションは、最初のセッションで話題を提起し、後の 2 つのセッションでそれを深掘りするという密接な関係なので、時系列ではなく、まとめて掲載します。

資料はこちらで公開されています(SPL-001 のみ)。
その他のセッション動画及びスライド資料も Channel9 で公開されています。
オープニング キーノートは Microsoft Virtual Academy のサイトで公開されています。

day 1

CODE ROOM TITLE
SNR-004 Room G デジタルテクノロジーが推進する、アプリケーション革新
SPL-001 Room C マイクロソフトが考える 5 年後を見据えた技術提言
CHK-002 Chalk Talk クラウドアプリケーションのアーキテクチャ設計を深める
CHK-003 Chalk Talk プログラミング パラダイムの知識を深める
CDP-008 Room C MS版Docker 誕生! Windows Server Containers とは?

day 2

CODE ROOM TITLE
ARC-001 Room A クラウド時代のデータアーキテクチャ
SNR-009 Room B フルスタックエンジニアとか無理!
比べてわかったAzure PaaSの勘所
DEV-019 Room F 徹底解説! プログラマーがおさえておくべき
Azure Active Directory のすべて
PBS-001 Room E ここまでできる! Office 365 API を活用したアプリ開発
~ Office 365 内のデータ活用~
DEV-006 Room A ASP.NET 5 Web 開発 ~ ランタイム編 ~
DEV-007 Room A ASP.NET 5 Web 開発 ~ フレームワーク編 ~
DEV-008 Room A 進化は止まらない! ADO.NET Entity Framework の今

SPL-001 マイクロソフトが考える 5 年後を見据えた技術提言

CHK-002 クラウドアプリケーションのアーキテクチャ設計を深める

CHK-003 プログラミング パラダイムの知識を深める

スピーカーは日本マイクロソフトの萩原 正義さん(SPL-001 / CHK-002)、荒井 省三さん(SPL-001 / CHK-003)、高添 修さん(SPL-001)。
この名前を聞くだけで MS 系エンジニアとしては期待が止まりません。

最初に、本セッションの内容は特定の製品技術についての話ではないこと、そして、既存製品の保守といった「守りの IT」ではなく、今後新規に開発するシステムのための「攻めの IT」の話であるという断りがありました。

続いて、今後の技術トレンドについて。いくつかのキーワードが出ました。

サービス化

IT システムも含めた様々なものが、所有から使用の時代になっていきます(その先は共有の時代)。

所有(もの) 使用(こと)
自家用車、分譲マンション レンタカー、賃貸
パッケージソフト クラウドサービス
買い替えの継続 常時改善
自己責任 保守保証
自己管理 監視、分析、予見

そして、サービスを提供して利益を上げていくためには、生産性を上げて、真似される前に新しいものを提供し続けていく必要があるとのことでした。
そのために必要なのが「早期投入」と「継続利用」です。

マイクロサービス

システムをこれまで以上に細かい単位で分割し、その単位で改善/差し替え/デプロイができるようにすることで、システムの進化のスピードをより上げることができます。「早期投入」に寄与する部分です。
マイクロソフトも先日 Azure Service Fabric という、マイクロサービスの構築を支援するサービスの提供を開始しました。

そうは言っても、皆さんはマイクロサービスという言葉をどの程度の粒度で捉えているでしょうか。
例えば当社ではeコマースサービスを提供していますが、これをマイクロサービスで設計するとしたらどうなるでしょう。
ぱっと思いつくのは「商品」「注文」「在庫」といった単位での分割でしょうか。

セッション中では、例えば「価格」というサービスを作るという例が出されました。

eコマース システムの典型的な ER 図は、こんな感じになるでしょうか。
f:id:cw_owashi:20150713191345p:plain
価格に関する項目が、多数のテーブルに登場しています。
もちろん、これで正規化された状態です。
単価が商品マスターと受注明細の両方にあるのは、受注明細の方は割引されているかもしれないとか、マスターの価格が改定されるかもしれないといったことに配慮しています。
受注に支払総額があるのは、送料や決済手数料といった、明細に属さない項目があるため、明細の小計をすべて足し合わせただけでは支払総額が求められないからだとしましょう。

ここでは、こういった設計の良し悪しを論じるのが趣旨ではありません。
ただ「価格」というありふれた概念であっても、それをどのテーブルに持つかは、システムの要求によって様々だということです。
そして、システムの要求はビジネス要件、ビジネスモデルです。
とにかくビジネスにスピードが求められる昨今、「価格はこのテーブルに持つ」といった硬直した設計では、ビジネスモデルを機動的に変化させて行けないということです。

そうは言っても、何でもかんでもマイクロサービスにすればいいというわけでもありません。
枯れた部分では、パフォーマンス的な利点などから、むしろ硬直的な設計にした方が良い場合もあるでしょう。
ビジネスにとって重要な部分、変化しそうな部分を見極めて、集中的にマイクロサービス化する必要があります。
想定が外れたらアーキテクチャの再設計が必要になるでしょうね。

また、マイクロサービスは単一の処理しかしないので、処理負荷が見積もりやすいというメリットもあります。
ユースケース単位では複雑すぎて、負荷を見積もるのが難しいのです(負荷に影響する要素が多いということだと思います)。
そのため、負荷が見積もれる単位でサービス化するというのも、サービス分割の一つの指針になります。

Docker

Docker は昨今、非常に注目を集めている仕組みです。マイクロソフトも多大な労力を投入しています。
Docker は、マイクロサービスを構築するための手段として最有力なものでしょう。

しかし、たとえば、マイクロサービス同士をどのように接続するかとか、サービスが停止した場合にどのようにリカバリーするかといった部分は、Docker の標準技術としては、まだ存在しません。
Docker との関連も含めて、マイクロサービスという概念自体が、まだそこまでこなれていないのが現状だということです。
今はまだ、プロダクション環境で全面的に採用するのは時期尚早だろうとのことでした。

パフォーマンス

萩原さんからはこんな質問がありました。

以下のうち、スループットに貢献するのは何でしょうか?

  • キャッシュ
  • パイプライン、プリフェッチ
  • OLTP、イベント駆動処理
  • マルチスレッド、ロックフリー
  • バッチ、キューイング
  • 複製
  • 圧縮
  • 非同期 I/O、Eventually Consistency
  • pushdown

pushdown というのは耳慣れませんが、データ操作の順番を変えて、早い段階で不要なデータをフィルタリングすることで、下流に流すデータ量を少なくする手法のことだそうです。

また、以下のような問いもありました。

  • スループットとレイテンシとスケーラビリティの区別がついているか
  • アーキテクチャが最も関係あるのはどれか?
  • コンピューターサイエンスが関係するのはどれで、工学的アプローチを取る必要があるのはどれか?

即答できるでしょうか?

答えはこうでした。

  • スループットに貢献するのはバッチやキューイング
  • キャッシュはレイテンシを下げる
  • アーキテクチャが関連するのはスケーラビリティ
  • スループットはアルゴリズムや I/O によって決まる
  • レイテンシは計測と改善を繰り返すしかなく、ボトルネックになる要因がいくらでもあるため、改善が最も難しい。理論では解決できない。

その上で、「良いアーキテクチャーとは、パフォーマンスの劣化が予見できるもの」としました。
OLTP やイベント駆動といったリアルタイム処理は、処理要求が捌き切れなくなった途端にパフォーマンスが急激に悪化する一方、バッチにはそのような閾値がなく、ロックも不要なので、パフォーマンス的には優れている処理形態とのことでした。

データパイプライン

こちらは「継続利用」の話です。
サービスを継続的に改善し続けていくためには、その材料になるデータを集める必要があります。
そのために必要なのが「データパイプライン」です。

システムのあらゆる層に存在するデータソースからのデータを収集し、蓄積し、変換し、管理し、分析し、可視化し、活用する。
こういった一連のデータの流れのことを、データパイプラインと言います。

関数型言語

オブジェクト指向言語から発展して、オブジェクト指向分析(OOA)やオブジェクト指向設計(OOD)といった手法も出てきました。
しかし、たとえば UML を例にとってみると、UML には様々な図がありますが、言語の機能と直接マッピングできるものはクラス図しかありません。
そのため、他の図をプログラムに落とし込む際には、どうしても属人性が生まれてしまいます。
デザインパターンなどを使って、なんとか手法を揃えようと努力していますが、成功しているでしょうか? 同じことを今後も続けていてよいのでしょうか?

荒井さんによれば、関数型言語の最大の特徴は「モジュール化のメカニズム=関数合成」があることだそうです。
合成する個々の関数が正しければ、それらを合成した関数もまた正しいことは証明済みなんだとか。
ただ、当日のセッション中では、「証明」という言葉は(Coq のような)数学的な定理証明ではなく、単に「十分にテストされている」という程度の意味で使われているようでした。
バグがない関数同士を合成したものにはバグがない、という意味で良いかと思います。
オブジェクト指向の場合、一つのメソッドやクラスを十分にテストしても、それを繋ぐ部分にバグが生じることは避けられません。

関数型言語は宣言的な言語です*1。従来のオブジェクト指向言語は手続き型の言語に分類されます。
手続き型の言語では、「データをどのように処理するか」を記述します。一方で、関数型言語は「データがどうあるべきか」を記述します。
「望んだ状態を得るためにどういう手順が必要か」ということを気にするのが手続き型言語で、気にしないのが関数型言語であるとも言えます。

.NET で関数型というと F# が連想されますが、LINQ も関数型の思想を取り入れた技術です。
例えば LINQ の Where メソッド は、foreach と if と List.Add 等を使っても実現することができます。
しかし、「Where」と書いておけば「データの絞り込みをしたい」というのが明らかですが、foreach と if と…では、一見して目的がわかりません。
Where には if 文相当のコードのみを書き、foreach に相当するコードは書かないので、テストをするのは if 文の部分だけで済みます。

また、CPU の性能向上のペースを表す、有名な「ムーアの法則」はご存知かと思いますが、このペースでの性能向上は既に技術的に限界に達していると言われています。
Pentium4 あたりまでは高性能のシングルコアプロセッサーが主流でしたが、それ以降はマルチコア路線になったのもこのためです。
この流れはさらに進み、汎用的な CPU と、専門的なロジックに特化した部品から構成される、ヘテロジニアス CPU という構成が一般的になってくるとのことでした。
これと関数型言語の話の流れがよくわからなかったのですが、良く使う関数は CPU に実装してしまうことで、コード内に書かれた関数と CPU 内の関数を「合成」してパフォーマンスを向上させることができるという話かなと思いました。
foreach で書いていると、どこが CPU に切り出せるロジックなのかわからないので、最適化が難しいですね。

それからもう一つ、関数型の重要な要素に、不変(Immutable)であることがあります。
関数型言語は副作用を持たないため、並列化がしやすく、先ほど言ったマルチコア化に向くだけでなく、クラウド化にも向いています。

問題指向

問題の解決の仕方を考えるのではなく、問題を問題のままシステム化していくことです。
一般に問題解決をプログラミングする上では、まず問題を定義する「問題ドメイン」を定義し、次にそれを解決するための「解決ドメイン」を作ります。
この時、「解決ドメイン」は複数の階層が作られ、次第に抽象→具体へと向かっていきます。

オブジェクト指向では、前述したように、抽象化の方法に属人性があるという弱点があります。
それを無くすためにはどうしたらよいか。
理想的には、問題ドメインを定義したら、それがそのまま解決ドメインに直結するということです。
そして、問題を解くための手順を書かない関数型言語は、それに近いことができるというわけです。

解決ドメインを作ることに割いていたコストを、ビジネス自体に目を向けるために使いましょう、とのことでした。

リアクティブ パラダイム

一般的なオブジェクト指向では、ひとつのオブジェクトが長い寿命を持ち、その状態が刻々と書き変わっていきます。
リアクティブでは、時間とともに状態が変わっていくのを、それぞれの状態のスナップショットを持った個別のオブジェクトの集合として扱います。
既にあるオブジェクトの状態を書き替えるのではなく、新しい状態を持つオブジェクトを作る。これは、関数型言語の不変性に似ています。

Microsoft の Reactive Extensions (Rx) が有名です。
Rx は .NET だけでなく様々な環境に移植されて活用されています。
また、Microsoft 発祥以外でも、Reactive StreamsReactive Manifesto といったものもあります。

Rx は LINQ に基づいて作られたライブラリで、LINQ は関数型の思想で作られたライブラリです。
このように、関数型とリアクティブは相性がいいので、関数型でリアクティブなシステムを FRP(Functional Reactive Programming/Paradigm)と呼びます。
また、時系列のデータを扱うので、データパイプラインとの親和性も高いと言えるかもしれません。

イベント

昨今、イベントソーシングという考え方が注目されています。
これは、システムに起こった変化をそのまま「イベント」として記録するというアーキテクチャです。リアクティブな感じがしますよね。
従来の RDB を用いたシステムでは、状態が刻々と変わる「テーブル」がデータの主体でした(オブジェクトに似ていますね)。
変更履歴のようなものを作るにしても、例えばデータベースのトリガーで生成するなど、あくまでテーブルが主で、履歴は従でした。
イベントソーシングでは、「システムに何が起こったか」という履歴を第一に溜め込みます。
そこから「最新の状態」を得るには、その履歴をすべて再生すればよいという考え方です。
実際にはパフォーマンス上の問題から、毎回すべてのイベントを再生するのではなく、最新の状態のスナップショットを持っておくこともあるかと思いますが、だとしても、履歴が主で、状態が従になります。

データベースでも Datomic のような、イベントを記録するタイプのものが出てきています。
このアーキテクチャは、既存のデータを変更せず、RDB で言えば INSERT しかないので、ロックが要りません。
一般的に、複数の操作の間で一貫性を保つロックやトランザクションといった仕組みは、並列処理やクラウドと相性が良くありません。

システム上で発生したイベントがすべて記録されているので、過去の状態を再現するのが容易で、トラブルシューティングが簡単というメリットもあります。
もちろん、大量のディスクスペースを消費しますので、資源が潤沢な現代だからこそ採用できるアーキテクチャと言えます。

クラウドのデザインパターンである CQRS(Command Query Responsibility Segregation)とも相性がいいですし、最近では Web フロントエンド向けのアーキテクチャとして注目されている Flux にも通じるものがあります。
そして、テーブルという概念を従に追いやることから、マイクロサービスの話に繋がる部分もあります。

関数型、リアクティブ、クラウド、マイクロサービスといった概念が一列に繋がってくるのには興奮を覚えますね。

プラットフォーム

これまで見てきたように、アプリケーションにはパラダイムシフトが起きつつあり、その形が大きく変わろうとしています。
それに対応して、より下層にも、要求に応えられる新しいプラットフォームが求められており、Microsoft はこれを「Cloud OS」と呼んでいるそうです。
これには、ハードウェア、OS、コンテナー、ミドルウェアなどの様々な要素が含まれ、数年前に Microsoft が Windows Server のことを指して「Cloud OS」と呼んだのとは異なる概念とのこと。

ハードウェアはより高速、大容量、省電力が求められており、Microsoft ではデータセンター向けの独自のハードウェアも製造しています。
また、その設計を Open Compute Project に提供することで、業界との協調を図っています。
このハードウェアは、汎用的なハードウェアと、Catapult と呼ばれる、処理をソフトウェアによって書き替えられるボード(FPGA)でできているそうです。

そのハードウェアの上に、Software Defined Infrastructure (SDI) が載ります。
SDI には、Software Defined Storage (SDS) や、Software Defined Network (SDN)、ハイパーバイザ、仮想マシン、API コントローラー等が含まれます。
また、サードパーティ製の製品がマーケットプレイス経由で提供されることもあります。

その上が、OS/コンテナーの層になります。
Microsoft は新時代の OS として「Nano OS」というものを設計しており、de:code でも注目を集めていました。
加えてコンテナーで、Immutable Infrastructure やパッケージングといった要求にも応えようとしています。
ここにも、マーケットプレイスからの製品提供があります。
現在でも Azure や AWS は仮想マシンイメージをマーケットプレイスで提供していますが、今後はコンテナー単位での提供が主流になっていくでしょう。

さらにその上が、タスク分散処理の層です。
クラウドでは多数のマシンによる分散処理が行われますが、どのタスクを、どのリソースが処理するかということを、この分散クラスタリング層が制御します。
ここで言う「リソース」とは「タスクを処理するナニモノか」のことで、これまでに見てきたハードウェア、インフラ、OS、コンテナーなどが含まれます。
ここには最先端の分散クラスタリング技術が投入されており、その内実は専門家でない我々に理解できるものではありませんが、活用することはできます。

システムの最終的な目標は「アプリケーションの実行」なのですが、そのために行うべきタスクは多岐に渡り、将来的には、その一部を専用ハードウェアに実行させるようになるそうです。
ハードウェアも仕様が公開されていてプログラマブルなので、マーケットプレイスからワンクリックで…とは行かないでしょうが、サードパーティが参入する余地があるのかもしれません。

このように、ハードウェアからインフラまで、プラットフォームを構成する様々な要素(リソース)がオープンに提供されることで、それらは競争し合うようになります。
セッション中ではこれを指して「Resource as a Service(価値の提供)」と呼んでいました。

*1:関数型言語を使っている方はご意見あるかもしれませんが、ここではそういうことにしておいてください。