FlaskにはWebサイト・アプリ全体に適用できるキャッシュ機構としてFlask-Cachingがありますが、最近よく見かけるAstroなどの静的サイト生成みたいに、最初から静的HTMLを生成しておいてFlask側で読み込むだけにした場合、Flask-Cachingを有効にしたWebアプリと比べて、どのくらい処理が高速になるか、簡単に実験してみました。
準備:
まずはFlaskアプリで自動生成しているWebページをhtmlファイルとして取得します。
テスト用に1~100までの連番ページを以下のコードでゲットしていきます。
import requests
import os
base_url = 'http://localhost:5000/' # ベースURLを指定
output_dir = 'static_pages' # HTMLファイルを保存するディレクトリを指定
os.makedirs(output_dir, exist_ok=True) # ディレクトリが存在しない場合は作成する
for i in range(1, 101): # 1から100までの連番でループ
url = f'{base_url}{i}'
response = requests.get(url)
if response.status_code == 200:
file_path = os.path.join(output_dir, f'page_{i}.html')
with open(file_path, 'w', encoding='utf-8') as file:
file.write(response.text)
print(f'Saved: {file_path}')
else:
print(f'Failed to retrieve {url}, Status code: {response.status_code}')
取得したhtmlファイルを静的HTMLとして配信するため、専用にルーティング設定をします。
# テスト用 / 静的HTMLを配置して表示させる
from flask import Flask, send_from_directory, abort
import os
# 静的ファイルが保存されているディレクトリ
STATIC_DIR = '<Flaskアプリのプロジェクトルート>/app/static_pages/'
@static_bp.route('/')
def serve_static_file(filename):
if filename.endswith('.html'): # HTMLファイルのみを提供
file_path = os.path.join(STATIC_DIR, filename)
if os.path.isfile(file_path):
return send_from_directory(STATIC_DIR, filename)
abort(404) # ファイルが存在しない場合は404エラー
あとは実際にアクセスして正常に表示されるかを確認した後、負荷テストをかけてみます。負荷テストにはLocustを利用しました。
比較用にFlaskアプリで自動生成の状態でも同条件でテストしています。
結果:
最大ユーザー数1800、秒間10ユーザー増加、wait_time を0.1~1秒間に設定して、3分間のテストを実行しました。
Flaskアプリのほうは、RPSが約350、平均レスポンスタイムが約3300ms、Failuresは3%となりました。

静的HTML配信のほうは、RPSが約650、平均レスポンスタイムが約500ms、Failuresは0%となりました。
Flaskアプリの高負荷時では、平均レスポンスタイム3300ms(≒3.3秒)となり、これはちょっと厳しいですね。負荷テスト中に手動でもアクセスしてみましたが、かなりストレスを感じる遅さでした。
一方の静的HTMLのほうは、最初にレスポンスタイムが6000msほどになる謎の山場がありますが、それ以降は500ms以下でサクサクと表示されます。
どちらのグラフも、RPSの伸びが途中で低下したり停滞しているので、それぞれこの環境では限界っぽいです。条件を変えて試行してみましたが同様でした。
まあ、静的HTMLのほうが速いのは自明で、さらにいえば、該当ページを設計上からもFlaskアプリから外してNginx 直配信にすれば、もっと高速化するはずです。
RPS(秒間リクエスト回数)が300というのは、1時間あたり108万(月間だと数億PVクラス)にもなるので、それだけのアクセス負荷を捌ければ十分とも言えますが、比較的容易に負荷耐性を2倍以上にできるのは嬉しいですね。