見出し画像

ファイルアップローダーサービスをローンチしました

はじめに

皆さんこんにちは、めもりー (@m3m0r7) です。

ファイルアップローダーサービスの enshared (https://ensha.red/ ) をローンチしました。

ローンチまで 2 週間程度、駆け足で実装してました。バックエンドエンジニアを自称しているハズなのに、ほぼフロントエンドしか書いてません。

なぜファイルアップローダーなのか?

ファイルアップローダーはユーザー入力が多いサービスです。一般的にユーザー入力が多いサービスは実装難易度が高く、いわゆる一般的なメディアサービスよりもより一層気をつけなければなりません。

そのため、より一層の知識を身につけるいい機会だと思い、作成することを決めました。

というのは後付で本当はなんかサービスつくりたいなぁ、手軽に作れるのないかなって模索して、ファイルアップローダーだったら「$_FILES でファイルあげて終わりっしょ笑笑」と軽い気持ちでやりました。すみません。本当はこんなに凝るつもりは 1 ミリもなく、 2 日 3 日くらいでできると思ってて、こんな時間かかる想定ではなかったんです。

一方で割と知識が要求される、というのが作っていての感想です。

例えば巨大なファイルが送られてきたときに PHP でどう処理するか?クラウドストレージとの連携をどうするか? E2EE をどうするか?ファイルのオプティマイズや、紐付け、データベース設計、インフラの設計、ZIP BOMB 対策、 CSRF、 キャッシュ戦略、 BOT 対策その他無限に考えることがありました。

実際にローンチしたあとにいくつか指摘をもらい修正をしていたりもしてました。 (TLS 1.0, 1.1 が有効になっている、選択できないバグがある、など)

とはいえ、入念にテストもしたので大きな障害はなかったのでめでたしめでたし。という感じです。

スマホは次時間に余裕ができたら出します。ごめんなさい。

技術スタック

技術スタックは非常に簡単で以下のようになっています。

- PHP 7.3
- Laravel 5.8
- React + Redux
- Apache + mod_pagespeed

バックエンド

PHP だと file_get_contents でやりがちですが、メモリ消費が著しくなってしまうので、file_get_contents ではなく、 Laravel の Storage Facade でやっています。下記みたいな感じで読んでそのまま出力しています。

$stream = \Storage::readStream($file->storaged->storage_id);
$remaining = $file->size;
do {
    echo ($read = fread($stream, static::CHUNK));
    $remaining -= strlen($read);
} while ($remaining > 0);

借りているのが VPS でメモリが残念なプランなのでいかにメモリを消費しないで済むか、という方向にも気を使っていました。

一部ファイルキャッシュ、一部 Redis, そしてファイル自体はクラウドストレージに置いています。クラウドストレージとはなるべく通信しないようにする戦略とかも考えてたりしました。こんなはずではなかった。

フロントエンド

フロントエンドは React Hooks + Redux です。 BFF は上記でも書いていますが Laravel です。

プロダクション環境に上げるまでに特に Lighthouse とか見ていなかったんですが、はじめに図ったときは

もちろんパフォーマンスなんて考えてるわけなかったので、結果は残念でしたが、他がグリーンになっていてラッキーみたいな気持ちでした。

最終的にパフォーマンスを改善して 60 台乗るようになりました。

画像1

ここらへんについては webpack でバンドルするサイズを減らしたり、 mod_pagespeed で改善したり、ストレージキャッシュ使ったり色々と考えていました。

最初はバンドルのサイズが 2MB くらいだったんですが、最終的に 750 KB くらいまで落とせました。物理世界もこれくらい痩せたい。

詳しく聞きたい方は登壇イベントなどに呼んでくれれば、喋ります。バックエンドでもフロントエンドでもどっちでもいいです。

もう少しパフォーマンスを改善する手立てはあるのですが、物理世界が割と忙しく、やりだしたらきりがないので一旦ここで止めています。

これもスマホ対応と同じで時間があればやります。


この記事が気に入ったらサポートをしてみませんか?