2014年11月15日、株式会社 サイバーエージェントセミナールームにて東京Node学園祭2014 が開催されました。本稿では基調講演の模様をレポートします。 
 
 
基調講演はNode.jsのリアルタイム通信モジュールであるSocket.IO  の作者であり、CloudUp というサービスを開発しているAutomatticのCTO、Guillermo Rauch(@rauchg )氏です。もうすぐ公開されるOSSのファイルアップロードツール「Party」の話を中心に、いまWebに不足している「ファイルアップロード」について話しました。         
 
 
拡がるSocket.IOの実用例  
日本のたくさんの会社が何年にも渡ってSocket.IOにパッチを送ってくれています。まずあまり知られていない大切なマイルストーンについて共有しました。 
Socket.IOが使われている例としてOffice.com  があります。Office OnlineやOffice 365でもSocket.IOでリアルタイムに編集やチャットができるようになりました。また、クラウドカスタマーサービスのZenDesk でもSocket.IOが使われています。    
最近みた面白い例としては、いわゆるIoT(Internet of Things)を挙げていました。OpenROV というDIYでできる小型潜水艦で、ブラウザからこの潜水艦を操作するためにSocket.IOが用いられています。     
ファイルアップロードの問題 
ファイルアップロードは、現在のWebでも難しい問題のひとつです。その原因は、そもそもHTTPがファイルを転送するためのものとして設計されてないためです。HTTP 0.9ではこのように定義されています。   
The response to a simple GET request in hypertext mark-up language(レスポンスは、シンプルなGETリクエストに対してマークアップで書かれたハイパーテキストである)  
 
ここでは、HTTPはASCII文字のバイトストリームというように書かれています。また、HTTPの名前をとってみても「Hyper "Text" Transfer Protocol」であるように、テキストの転送をするためのものとして設計されているのです。     
今ではあまり使われていないFTPというプロトコルはそのためにあります。なんといっても「File Transfer Protocol」なのですから。しかし、たくさんの欠点があるためあまり使われていないのが現状です。例えば、FTPでは特別なTCPコネクションを必要とし、FTPを使う際には2つのTCPコネクションが必要となります。また、ファイルの転送という点でも、圧縮できるのはテキストだけでバイナリデータについては圧縮が適用できません。さらに、セキュリティの面でも問題があるためどんどん使われなくなっています。        
FTPをWeb上で使うにはさらに問題があります。ファイルダウンロードのために同じTCPコネクションをHTTP、FTPで共有できないため、多くのオーバーヘッドがあるからです。一方で、HTTPは機能が追加されMultipart Uploadが可能になり、バイナリデータのアップロードが可能になりました。また、ASCII文字以外のデータのダウンロードも可能になりました。ただ、Web上でのファイルアップロードに関しては、今でも簡単になったりより良くなったりはしていません。       
ファイルアップロードに確実に足りてない機能は「ポーズ・レジューム」機能です。加えて、自動リトライの機能もないので、アップロードが失敗した時のエラーハンドリングについても自分で行う必要があります。チャンクに分割する機能も不足しているので、並列でアップロードもできなければ、圧縮もできません。これらはアップロードの速度がとても遅かった時はあまり問題ではありませんでしたが、アップロードの速度が速くなった現在では問題になっています。また、ダウンロードでは圧縮ができますがアップロードではできません。         
JavaScriptによる解決 
「今日は今考えている解決法を紹介したいと思っています。その方法は、皆さんがよく知っているJavaScriptを使う方法です」と、現在Guillermo Rauch氏が開発している「Party」というライブラリを紹介しました。     
ベースとして使う機能はXMLHttpRequest2(XHR2)です。プログレスイベントを使って、クライアントがTCPコネクションでの進捗を取得できますし、バイナリサポートもあります。そしてFile APIのBlob#sliceなどを使うことで実際にアップロードする前にファイルのバイナリデータを操作できます。Partyではその2つのAPIを使って、ファイルのアップデートをより簡単に強力に行えるようにします。     
今までのWebサービスの作り方では、大きなフレームワークの中で、アップロード用のルーティングを設定したり、アップロードのためのモジュールを追加したりすることが一般的でした。しかし、Partyでは1つの専用のアップロードサービスとなるように作っています。    
この新しいシステムはHTTPを使ったファイルストリームというよりはBitTorrentとよく似た仕組みのシステムになっています。
1つの独立したサービスにすることによるメリットは2つあります。ひとつはセットアップ時にクライアントサイドのJavaScriptと別に扱えることです。もうひとつは、CDNでの配信を簡易化できることです。 
これらについて、デモサイト を使ったデモがありました。サーバ側ではSocket.IOのようにパスを設定するだけでアップロードサービスが提供できるようになります。アップロードされたファイルをストリームで扱えたり、メタデータを追加することもできます。クライアント側ではblob, array buffer, file referenceのいずれのデータもバイナリ構造のデータとして扱うことができ、XHRとは異なりアップロードの進捗や失敗を通知することができます。   
 
 
サーバ側のコード 
 
 
クライアント側のコード 
 
 
また、Partyではファイルを分割してそれぞれ異なるTCPコネクションでアップロードしたり、圧縮を使うことで高速化もしています。デモにおいても通常のファイルのアップロードの半分の時間でアップロードができることを示しました。並列にTCPコネクションを使ってアップロードすることで、それぞれのスライディングウィンドウを大きくでき、スループットを最大化できるそうです。また、圧縮という点でも現在Google Chromeのみで使えるWebsocketのDeflateを使ったり、asm.jsで作成したzlib.jsを使うことで高速化していますが、この部分はPartyがハンドリングしているので開発者はこれらを気にすることなく開発できます。         
ファイルを分割することによるメリットは、信頼性を高めることにもつながっています。従来の方法では、ファイルの90%がアップロードされた時点でブラウザがリフレッシュされると、また最初からアップロードするしかありませんでした。しかし、Partyを使えばその続きからアップロードすることができ、サーバに送れていない部分だけをアップロードすることが可能となります。これにより、ネットワークの環境がよくないブラウザでも、安定してファイルのアップロードができるようになります。       
さらに、Partyでは開発者が自由に使えるようにポーズやレジューム機能も提供しています。これらが実現できているのは、File APIを使ってファイルのユニークな識別子ETagを作ることができているからです。ファイルの変更時間、名前、ファイルサイズなどを用いてユニークな識別子を作成できます。もし必要であれば、ファイルのバイナリデータを用いてCRC32やMD5のような高度なハッシュメカニズムも使用できます。     
これらはデフォルトでHTML5のWorkerを使うことでノンブロッキングに実行されます。ファイルの分割、同期、リトライなどはすべて独立したWorkerの中で動作します。また、認証や設定などもフレキシブルに行えるようになっており、ミドルウェアのような機能を提供します。サーバがクライアントに転送可能な最大サイズや、チャンクのサイズ、チャンクが送られてこない時にファイルを破棄するまでの時間などが設定可能です。ユーザ認証も好きなものを使えます。      
現在はAutomattic の新しい商品のために開発中で、もうすぐGitHub上でオープンソースになる予定です。 
質疑応答 
Q.  File APIなどの新しいAPIを使う時に仕様が固まっていませんが動作が不安定だったり、不安になったり、もう少しこうだったらいいのに、と思うことはありますか?   
A.  File APIに関しては仕様も固まっており、XHRと組み合わせて使っています。現在気になっているのは、Stream APIの仕様がまだ固まっていないことです。Streamのシミュレートを試しましたが、パフォーマンスの面であまりよくありませんでした。Stream APIはまだまだ改善していく必要があります。   
Q.  iOSやAndroidのモバイルブラウザでも使えますか?
A.  モバイルブラウザ対応は素晴らしいです。ただ、モバイル向けブラウザのボトルネックはメモリアロケーションの部分と、アップロードを同期的に行う必要がある点です。そのため複数ファイル選択を一部機種で行わないようにしてWebViewがクラッシュするのを防いだり、並列数に制限をつけるなどの最適化をしています。その甲斐あってか、すべてのAPIがテストした多くの機種でよく動いています。    
まとめ 
Partyは、Webサービスを作る上でファイルアップロード機能をより簡易に導入できるJavaScriptのライブラリです。開発の際にボトルネックになりがちな並列アップロードや圧縮を解決し、ポーズ・リジューム機能を実現します。現在、Guillermo Rauch氏を中心に開発が進められており、近日AutomatticのGitHub 上にてオープンソースとして公開される予定です。デモで感嘆の声が上がるなど、大盛況の基調講演でした。