真にサーバレスを実現するにはどうしたら良いか

ハッキリ言います。これはテックポエムです。

そもそも 真にサーバレス とは?

昨今のサーバレス技術っていうのは、一言で言えば ただの FaaS (Functions as a Service) で、

サーバのインフラを管理しない と言う意味でのサーバレス

だと個人的には考えていて、これはこれで便利かつコスト的にも節約できるとは思っています。

ただ、とは言え、

どっちにしろ(サービスの提供側が用意する)実行サーバ有るじゃん

という印象が個人的にはあり、実際のところ FaaS やそれに相当する環境をオンプレで用意していたとしても、 その FaaS 側でひとたび障害が起きれば、そのFaaS に依存したサービスは巻き添えを食うワケで、 そう言った意味では、FaaS は、

マネージドサーバレス ではないか?

と思うんですよね。

それで、もしこれを、

既存のエコシステムサーバを用意せずにアプリを構築する

と言うコトにチャレンジするとするならば、どの様にするのが良いのだろうか……と言う様なことを、 以前からちょくちょく個人的には考えていたのですが、最近になって、

あ! こう言う感じの仕組みを用意すれば、既存の技術だけで出来るんじゃね?

と言う思い付きが最近有ったので、今回はそれを忘れない内にポエムとして書いておこう、 というのが今回の記事の主な目的です。

真にサーバレス を実現するための条件

まず、基本的に Web アプリケーションであれ何であれ、アプリケーションの実行基盤として必要な要素は、

  1. アプリケーションのコードを 実行する こと
  2. アプリケーションのデータを 保存する こと
  3. アプリケーションのデータを 共有する こと

の3つ、と個人的には考えています。

つまり、 真にサーバレスなアプリケーションプラットフォーム構築する ためには、

上記の3つを サーバを用いずに実現する ということを行えば良い

というコトになる、と私は考えています。

真にサーバレス な環境を構築するための技術選定

1. アプリケーションのコードを 実行する

これについては、まず、

  • Service Worker を使う

というのが、現状の技術ではもっとも近道だと考えています。

と言うのも、

  • デスクトップ環境
  • モバイル環境
  • タブレット環境

という3つの環境で、 現実的に共通のコードで取り扱える技術 と言ったら、 Web ブラウザに搭載された Service Worker ぐらいしか無い ので、 銀の弾丸では無いけれども、Service Worker なら行けるんじゃね? 的な観点で選定しておきます。

2. アプリケーションのデータを 保存する

正直、これは、

真のサーバレス を実現するための難題の一つ

だと感じているのですが、これについては基本的に、

Web Storage API でなんとかする

ぐらいしか無いんじゃないかなぁ、と思っています。

と言うのも、ブラウザの API 経由で叩けるストレージ系の API って Cookie とかこれぐらいしか無いので、 ある程度の容量の制約が付くにしても Web Storage API で頑張るしかない、と個人的には思います。はい。

3. アプリケーションのデータを 共有する

で。 最後の難題 がコレ。

正直言うとこれは WebRTC を使ったブラウザだけの P2P でなんとかする 以外、方法は無いんじゃないか……と思うのですが、 今のところ WebRTC をどの環境でも完全に繋がる様にするため には STUN とか TURN のサーバを用意する必要がある ため、

(商用サービスとかだと)完全なサーバレス、無理じゃね?

となるのですが、とりあえず 繋がらない環境も有ることを許容する ことにしてしまえば、

WebRTC で P2P データ共有する

というのは一つの選択肢になるのではないか、と考えています。

しかし先程サックリと WebRTC で P2P する とか言いましたが、現実問題、

WebRTC を使ってスケールする P2P アルゴリズムを書く

と言うのは、結構難題(と言うか私の力量では多分ムリ)なので、ここでは一応既存の WebRTC 上の P2P 技術として、

を選択することにします。ちなみに WebTorrent とは BitTorrent Protocol に相当するアルゴリズムを WebRTC 上で実現したライブラリです。はい。

真にサーバレスなアプリを実現するために考えなければならない事

1. 上記3つの技術をどう組み合わせるか

基本的に、これは一言で言えば、

Service Worker な SPA で Web Storage API + WebTorrent でデータを保存しつつ共有

という事になるハズ……なんですが、やっぱりこれには幾つかデータ共有上の問題があって、

アプリの Bootstrap 時のアプリのコードとデータ共有はどうするのか?

と言う問題と、あと、

WebTorrent が静的な情報しか共有できないのはどうするのか?

と言う問題があります。

それで、まずアプリの Bootstrap については 真にサーバレスなアプリを Web アプリとして配信する 限り、 どこかの ファイルホスティングを用いないとどうしようも無いので、ここでは妥協して CDN などを用いて配信する ことしますが、 問題は、

WebTorrent が静的な情報しか共有できない(と思われる)

と言う点です。

それでこれはどういう事かというと、恐らくはWebTorrent が BitTorrent Protocol を再現したライブラリであるが故の制約だと思うんですが、 BitTorrent Protocol 自体が、常に変化する情報を共有するということを想定されていない

Server-Client モデルと P2Pモデルを組み合わせた Hybrid P2P モデル

を採用しているため、Twitter とかで見られる様な ストリームを常に更新し続ける という部分については、 WebTorrent 単体では実現できそうにありません

つまり、ある時点A での最新の情報がどのデータかを指すポインタとなる情報 については、 別のプロトコルで実現する他ない と言うのが現状で、データを配信する部分には WebTorrent を用いられる にしろ、 データを WebTorrent で共有するための情報 については、 時前で色々と実装する必要があります

それで、この辺りに使える技術というと、これについては、

分散ハッシュテーブルを実現するアルゴリズム の1つである Kademlia

が使えそうだ、と今の時点では思っていて、なぜ kademlia かと言うと、

  • npm では Kademlia を実現するためのライブラリが揃っている
  • Kademlia は P2PノードのJoin/Leave が頻繁なネットワークで壊れにくい
  • Kademlia はアルゴリムがシンプルで理解が比較的容易である

という辺りです。そのため、実際に P2P on WebRTC で情報をやりとりするためには、

Kademlia を用いたネットワークで WebTorrent の為の情報を共有する

という感じになるのではないか、と考えています。

2. 真にサーバレスな環境でデータを保存・共有する際の構造について

さて、ここまで述べて来たことをここで一旦まとめると、

  1. アプリは Service Worker + Web Storage API + WebRTC をコア技術として使う
  2. 情報は Kademlia ベースの DHT + WebTorrent で共有する
  3. Bootstrap 問題は CDN でアプリのコードを配信するなどする

という感じになるのですが、ここから更に考えなければならないのは、

P2P で流通させるデータの構造はどうするか

という点です。

これはどういう事かというと、先にも述べた通り WebTorrent では動的に変化し続ける情報は取り扱えず 、 その辺りを Kademlia なネットワークでサポートする必要がある ワケですが、P2P で情報を共有する以上、 単体のデータそのものに情報の関係性(例えば、時系列や前後関係)を組込まないと、 そのデータがどこで何に必要な情報なのか、というのが判別出来なくなります

また、P2P で情報をやり取りする関係上、データの受信順序がデータ同士の関係性とかならずしも一致するわけではなく 、 実際のデータの受信順序は データ同士の関係性とは無関係なランダムに受信する可能性が高くこの辺りを考慮したデータ構造を用意し、それを P2P ネットワークで共有する 、という形を取らざるを得ません。

それで、ではここでどういったデータ構造を用意すれば良いか……という話になるのですが、 これについては、

CRDT という特性を満たした Blockchain 状のデータ構造を用意する

と言うことで実現可能ではないか、と考えています。

それで、 CRDT というのは Conflict-free Replicated Data Type の略で、このデータ構造についての話は、

[https://qiita.com/everpeace/items/bb73ec64d3e682279d26:embed]

という Qiita の記事が詳しいのですが、一応かいつまんで説明しておくと、CRDT とは、

すべてのデータをマージし続けた結果が常に同一となるデータ構造

の事(だと私は理解している)で、これは **情報の取得が順不同 でも 結果整合性が保たれる ** という性質のデータ構造の事です。

また Blockchain 状のデータ構造 というのは、別に Proof-of-Work を組込めとかそういう話ではなく、

単体の情報そのものに、その情報の前後関係に当たる情報を組込む

という類いの話で、つまるところ、これは Blockchain の様に P2P で共有する情報そのものに、 前後関係のアドレスハッシュ等 を組込み それを鎖状に連鎖させる 、という事が必要になると言う事です。はい。

3. ネットワークへの攻撃に対してどう対処するか

それで、 真にサーバレスなアプリケーション で最後に考えなければならない事は、

そのアプリケーション上のネットワークで、どう情報の信頼性を保証するか

という辺りです。

ここでいう 情報の信頼性 とは、 **情報の内容が信頼できるか という問題ではなく、流通する情報自体が改竄などの攻撃を受けていないか ** を チェックする必要がある、 という類いの問題で、この辺りについては、

WebCrypto API で公開鍵認証をベースとした電子署名を行う

と言うことで改竄は検知できるかと思います。

ただし、WebCrypto で改竄を検知したとしても、なり済ましなど、

その電子署名の署名者 が、 真にその人当人であるか?

については、完全に別の方法で実現するしかないので、その辺りはアプリケーションの性質にも依るのかな、と思います。

その他考慮すべきこと

ここまでに書いてきた内容では、

真にサーバレスなアプリケーションを構築するにはどうしたら良いか?

と言う事ですが、他にも真にサーバレスなアプリケーションを構築するためには、

真にサーバレスなアプリでの違法な情報や違法な行為をどう抑止するか?

という事や、あるいは、アプリが使う帯域の制限 や、 何か問題が起きた際どうやってアプリを停止させるか など、 他にも 実装面倫理面 で考慮すべき事柄はあると思います。

また、今回は特に取り上げませんでしたが、

課金にはどうやって対応するか

など、アプリは作れてもビジネスになるかどうか と言った問題もある ので、

真にサーバレスなアプリケーション は一筋縄では実装できない

と言えるとかと思います。はい。

以上

ゆるふわテックポエムを書くつもりが、結構ガッツリとした文字数に成ってしまったでござる……

nyarla が大体ぐらいに投稿