Google Cloud Storageのモバイル対応は残念な点 およびAmazon Cognitoはすごいという話
今年も年の瀬、最後は一応技術ブログなのでプログラミングの話題で締めます。
モバイルアプリでユーザが画像や動画を投稿するサービスを作る際、バックエンド側のエンジニアが最も腕の見せどころとなるのはレスポンスの早さです。バックエンドにかぎらず、フロントでもバックグラウンドでアップロードさせるとか、細かいローダーをどのように表示するかで体感速度を向上させるわけです。 Amazonではサイトの表示が10ms(=0.01秒)遅くなると売上が~~という話がよくあります。というわけで多くのサイトは200msとか目標を決めてサーバのレスポンスをなるべく早く返しています。だから遅くて1秒、2秒かかるサイトはあっても10秒以上かかるサイトはあまりありません。(ここで言ってるのはサーバの速さです)
一方でモバイルアプリのアップロードはそれとは違い、15秒撮影した動画をアップロードするのに1秒2秒で済むということはありません。iPhone6で加工してない動画を撮影すると1秒あたり2~3MBになりました。 この数字だと回線状態が悪いと10秒とか20秒、あるいはもっとかかるくらいのサイズなのでアップロード中の離脱が増えてしまいます。
モバイルから直接アップロードする
画像や動画をアップロードする際、自社のサービスのサーバ(以降APIサーバ)に送って保存+リサイズ等行うのが多いみたいですが、この方法だとAPIサーバからさらにストレージサービス(s3やGoogle Cloud Storageなど)への転送時間がかかってしまいます。 もちろんこれを非同期にすることは可能ですが、今度はAPIサーバに動画・画像の転送処理というバッチ的な機能を持たせる必要があります。これは例えばRailsでAPIを書いてる時、APIサーバ群とバッチ(ActiveJobなど)サーバ群の構成を分けたいときにAPIが一部でバッチ的な役割も担う必要があって見通しが悪くなります。
そこで理論上、モバイルアプリが直接ストレージサービスに画像等をアップロードしてから、そのURLをAPIサーバに送り、さらにバッチサーバでリサイズ等処理をするのが無駄のない処理になります。
このことを言ってくれてるのがこちらの記事です。
で、ここからが本題なんですがs3でできるならCloud Storageでも同様にできるだろうと思い資料を探してみました。 ところが、結論から言えばCloud Storageではこれはできません。(間違ってたら教えて下さい)
そもそもCloud StorageのiOSライブラリはいまだにobjc版だったりARC対応してないなどインストールだけでも大変だったんですが、どうやらAPIの権限上の問題でユーザが投稿することを認めていません。
Cloud StorageのAPIについて
APIのキーがいくつかあって混乱します。 まずセキュリティ上、iOS側に渡しても問題のないキーは一番上のiOS APIキーになると思います。(一応DeNAのプラットフォームの友人に聞いて確認しました) そのほか、例えばサーバキーやサービスアカウントのOAuth認証をユーザに渡すとリバースエンジニアリングのリスクがあるわけです。
で、ポイントはiOS APIキーはサービス全体に紐づくデータやユーザデータに対する権限をあまり持っていないということです。iOS APIキーで調べると一番上にはGoogle Mapのサンプルが出てきます。こういうユーザやサービスにあまり直接かかわらないAPIを操作するためのキーだと思われます。
したがってiOS APIキーではCloud Storageに画像をアップロードすることはできません。
もう一つの方法はユーザがアプリ上でGoogleログインして、アプリに対して認可をくれればそこでもらったOAuthトークンでユーザの画像を作ってやることができますがこれは今回のユースケースとは違うので除外します。
試してないのですがサービスアカウントをハードコーディングせず各ユーザに対して動的に付与してやる方式ならうまくできるのかもしれません。
Amazon Cognito
というわけでAmazon Cognitoの出番です。Cognitoは要するに端末ごとにユーザを識別してくれるサービスです。内部的には初回起動時にユニークIDを付与し、keychainに保存しているようです。
で、ここはわりとブラックボックスになっているのでまだ把握できてませんがCognitoを使えばAWS側が端末を識別できているので、こちらが持っているs3に画像をアップロードできます。
試しに使ってみたら非常にカンタンにアップロードできたので、とりあえず今回はこのアップロード限定でs3を使うことにしました。
Cloud Serviceの一本化/併用は考えて行う
私は普段Google Cloud Services一本なんですが、Googleが持ってないものでAWSが先行しているもの、およびその逆が意外とあることを今回痛感しました。例えばEC2 vs Compute Engineなどはさすがに一本化していいと思いますが、各サービスの利点をうまくとりいれつつ、互いが邪魔しあわないようにうまく住み分け/インテグレートしていくチョイスが今後重要になるのではと思います。
クラウドなんちゃら
クラウドファンディング、クラウドソーシング、クラウドテクノロジーとかここ最近になっていっぱい出てきたけど、Crowd(群衆)とCloud(雲)でそれぞれ意味違うからね。
Gemを作って公開する本当のメリット
Gemを作って公開すると、誰かに気に入られると多くの人からスターが付いてPRが来たり、自分の名前が売れる。 それだけで満足感があったり、転職活動に有利なのだけどプログラミング上の本当のメリットは次のようなことだと思う。
def method_missing(method, *args, &block) case method when METHOD_PATTERNS[:callback] filter = $1.to_sym name = $2 if callback = args.shift set_callback name, filter do if respond_to?(callback, true) send(callback) else instance_eval(callback) end end end if block.present? set_callback name, filter, &block end else super(method, *args, &block) end end def respond_to?(method, priv = false) METHOD_PATTERNS.values.any? { |pattern| pattern =~ method } || super(method, priv) end
ちょっと今仕事で保守しないといけないアプリケーションのソースにこういうのがある。 で、これって書いてる時はいいんだけど読むのは辛いし、読めた所で動的ディスパッチが多いので結局周辺情報まで辿っていかないと意味がなくて、デバッグ上のコンテキストとか依存性が大きすぎるんだよね。
というわけで、ここでエラーが起きたとしてこのコードが間違っているのか、はたまた実行環境(インスタンス変数とかの状態)がおかしいのかがわかんない。
で、Rubyってmethod_missingとか使いまくるとどうしてもこういう傾向が強くなってしまうので、こういうライブラリ的なコードは外において切り離し、他の人や他のプロジェクトから使用してもらって実行環境に依拠せず動くかとか、ライブラリにバグがあったときはレポートしてもらうorあわよくばバグフィックスしてもらって、とにかく自分のビジネスコード側にあたりをつけてデバッグできるようにしたほうがずっと楽なんですよ。
というわけで、こういうコード書く時は小さいgemにして公開しておくのがいいと思います。まぁはっきりいってアプリケーションの中に唐突に出てくるこういうコードはクソースですね。まぁ2年前の自分が書いたんだけど。
アイアがパクられたわけだが
僕ね、この会社知ってたんですよ。
実は2011年くらいに「和風な名前のシードVC」が主催するS◯Sというイベントに行ったことがあります。
渋谷から15分くらい歩いた、渋谷にこんなとこあるんだ的な狭い建物でやってて、そのときはホントに聞いたこともないベンチャーがうじゃうじゃ集まってました。(ちなみに当時の覚えてる会社で今有名なのはnagisaです)
で、なんかしらんけどこのアイアも参加してたんですね。
というのは、50社くらいで4時間耐久ピッチみたいなのやってたんですけど、そのピッチがずいぶん悪い意味で印象に残った。4年以上前のことなんで不正確なとこもあるかもですが、記憶の限り再現した様子がこんな感じ。
???さん「じゃ次行きましょう!!!!!! サ◯ライ〜〜シャウっ!!」(聴衆≒出資受けた人たち一同 サ◯ライ〜〜シャウっ!)
アイアの人「こんにちは〜〜!」
一同(こんにちは〜〜! 酒を飲みながら)
アイア 「僕はアイアって会社でチャクラっていう雑誌を作ってますーー!」
「まぁこれはスピリチュアル系の雑誌で、パワースポットを紹介したりパワーストーンを販売したり、ちょっと残念な人たちに読んでもらってる雑誌でーす!」
一同 爆笑
アイア「この間は中国のスピリチュアルな石を応募景品にしたんだけど、石の手配が遅れちゃって予定日までに届けられなかったんですよーー」
「でも、『今パワーを込めてるんですが念能力者のパワーの充電に時間がかかってるんで待ってください』って言えば、簡単に騙せるんですよーー。『それならパワーいっぱい込めてください!』みたいな!! しかも石もそのへんの石なんですけどねww!!」
一同 大爆笑
アイア 「そんな僕らですけど、よろしくおねがいします〜〜!」
一同 大拍手
いや、この会社はアウトだし、笑って聞いてちゃダメだろと
ちょっと僕の記憶が経年で誇張されてるかもしれないので、当時を覚えてる人がいたらコメント等で教えてください。つーかなんでこんなベンチャーでもないただの悪質出版社がSV◯に紛れ込んでたんだろう
逮捕怖い
いやー、IT系の人が逮捕されてますね。小学校のとき教師に言われたことを覚えてるんですけど、逮捕される犯罪者で犯罪を犯そうと思って逮捕された人は少ないんですよね。
だいたいは、ついうっかりやってしまったことが結果的に犯罪になったとか、かっとなって人殴ったとか。
要するに普通の人なんです。おそらく犯罪者の中で振り込め詐欺グループをやっていたというような、逮捕事由だと理解しながら動いていた人は少ないし、そもそも逮捕されることだとは思っていても事実上検挙されない(これはセーフ、逮捕は他人事)と思ってた人が多いと思う。
でも逮捕って要は警察の胸先三寸で、さらに言えば裁判に勝ったところで「(実名) 逮捕」っていうニュースは残り続けるんで意味ないんだよね。
ここ最近、私のまわりにこういう人がいました。
・新宿の裏スロットにたまに行ってる人
・事業をやるためにそのへんの人に頼んで曖昧な契約でお金を預かってる人
・youtubeに上がってる動画をダウンロードして、動画内に広告を付け足して別の動画としてアップロードしてる人
これ全部警察が本気出せば逮捕されて実名さらされる案件のはずです(と、私は理解してます)。
そもそも逮捕で実名出すのは公権力が不当な拘束をしないよう市民にしらしめ、かつ累犯を予防するのが実名公表の趣旨なような気がしますが、事実上は犯罪者の烙印を一生背負い続ける制度になってるので気をつけたほうが良いですね。