FlaskのAPIで非同期処理を実現する方法!Celeryを使った実装を初心者向けに解説
生徒
「FlaskでAPIを作ったんですが、処理が遅くてページが固まります…。何か方法はありますか?」
先生
「FlaskのAPIで重い処理を実行すると、リクエストが終わるまで待たされてしまいます。そんなときに便利なのが、非同期処理です。」
生徒
「非同期処理って何ですか?」
先生
「簡単にいうと、『待たずに裏で仕事をしておいて、終わったら結果を教えてね』という仕組みです。FlaskではCeleryというライブラリを使うのが一般的です。」
1. FlaskのAPIで非同期処理が必要な理由
Flaskは軽量で使いやすいWebフレームワークですが、標準の動きではすべての処理を同期的に実行します。例えば、画像処理やメール送信など、時間のかかるタスクをAPIで実行すると、その間ユーザーは待たされ続けます。これでは、ユーザー体験(UX)が悪くなります。
そこで、Flaskでは非同期処理を導入します。非同期処理を使えば、APIはすぐにレスポンスを返し、重い処理は裏で実行できます。まるで、レストランで料理を頼んで、席で待っている間に他のことができるようなイメージです。
2. 非同期処理とは?初心者向けに分かりやすく解説
「同期処理」と「非同期処理」の違いを簡単に説明します。
- 同期処理:処理が終わるまで次の作業に進めません。例:ラーメン屋で、ラーメンが出るまで立ったまま待つ。
- 非同期処理:処理を頼んだら、別のことをしながら待てます。例:ラーメンを頼んで、席に座ってスマホをいじって待つ。
Flaskに非同期処理を導入することで、ユーザーはすぐに「リクエストを受け付けました」という返事をもらえ、その間に裏で重い処理が進みます。
3. Celeryとは?
Celery(セロリー)は、Pythonで非同期処理を簡単に実現できるライブラリです。Flaskと組み合わせることで、重いタスクをバックグラウンドで実行できます。
Celeryの特徴:
- タスクキューを使って、複数の処理を並行して実行可能
- RedisやRabbitMQといった「メッセージブローカー」が必要
- Flaskとの統合が簡単
イメージとしては、Celeryは「タスクを運ぶお手伝いロボット」です。Flaskから「これをやっておいて」と指示を出すと、Celeryが裏で処理を進めてくれます。
4. Flask + Celeryを使った非同期処理の実装例
ここでは、Flaskで「重い処理を非同期で実行するAPI」を作ってみます。
4-1. 必要なライブラリをインストール
pip install flask celery redis
4-2. FlaskとCeleryの設定
from flask import Flask, jsonify, request
from celery import Celery
import time
app = Flask(__name__)
# Celeryの設定(Redisをブローカーとして使用)
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
# 非同期タスクの定義
@celery.task
def heavy_task(duration):
time.sleep(duration)
return f"{duration}秒の処理が完了しました!"
@app.route('/start-task', methods=['POST'])
def start_task():
data = request.get_json()
duration = data.get('duration', 10) # デフォルト10秒
task = heavy_task.delay(duration) # 非同期でタスクを実行
return jsonify({'task_id': task.id, 'status': 'タスクを受け付けました!'})
@app.route('/task-status/<task_id>', methods=['GET'])
def task_status(task_id):
task = heavy_task.AsyncResult(task_id)
if task.state == 'PENDING':
return jsonify({'status': '実行待ち'})
elif task.state == 'SUCCESS':
return jsonify({'status': '完了', 'result': task.result})
else:
return jsonify({'status': task.state})
if __name__ == '__main__':
app.run(debug=True)
4-3. 実行方法
- Redisサーバーを起動(Dockerを使うと簡単です)
- Flaskアプリを起動:
python app.py - Celeryワーカーを起動:
celery -A app.celery worker --loglevel=info
この構成で、Flask APIにリクエストを送ると、裏でCeleryが重い処理を担当します。
5. 実際にAPIを試してみる
ターミナルやAPIツール(Postmanなど)で以下のリクエストを送ります。
タスクを開始
curl -X POST http://127.0.0.1:5000/start-task -H "Content-Type: application/json" -d '{"duration": 5}'
結果の確認
curl http://127.0.0.1:5000/task-status/タスクID
6. 非同期処理を導入するメリット
- ユーザーを待たせない:APIがすぐにレスポンスを返せる
- 処理の並列化で効率アップ
- メール送信、画像変換、大量データ処理などに最適
Webサービスを作るうえで、非同期処理は欠かせない要素です。FlaskとCeleryを使えば、初心者でも比較的簡単に導入できます。
まとめ
FlaskでAPIを開発する際に問題になりがちな「重い処理によるレスポンスの遅延」を、非同期処理によってどのように改善できるかを総合的に振り返ります。とくに、画像処理や長時間のデータ集計、外部APIとの通信など、ひとつのリクエストで多くの時間を必要とするタスクは、同期処理ではユーザー体験を著しく損ないます。こうした場面において、Pythonで広く利用されているCeleryと組み合わせることで、Flaskアプリケーションは高い拡張性と柔軟性を獲得できます。非同期処理が持つ本質的な利点は「待ち時間を切り離す」ことにあり、タスクキューという仕組みを利用することで、アプリケーションは素早くレスポンスを返しつつ、裏側で必要な作業を進められるようになります。 さらに、CeleryはRedisやRabbitMQといったメッセージブローカーを活用することで、複数のワーカーが同時にタスクを実行できるため、大規模なバックグラウンド処理にも対応できます。タスクをキューに積み、別プロセスで実行するという流れは、サーバーの負荷を分散し、API全体の処理速度を向上させる効果があります。FlaskとCeleryの組み合わせは、学習コストが低いにもかかわらず、商用レベルの高い信頼性を持つ構成としても知られています。実際の開発現場でも、メール送信、レポート生成、動画変換、AI推論処理など、多岐にわたる用途で利用されています。 また、今回の実装例では、FlaskのルートからCeleryのタスクを呼び出し、処理開始のレスポンスと、タスクIDを使った処理状況の確認という2段階構成でAPIを設計しました。これにより、ユーザー側は即時に「処理を受け付けました」という応答を受け取りつつ、必要に応じて後から結果を取得できます。この仕組みは、非同期APIの基本的な構造であり、より高度なアプリケーションでは、タスク完了時にWebhook通知を送ったり、フロント側でポーリングして状態更新を行ったりといった応用にもつながります。Redisサーバーを利用する設定はシンプルで扱いやすく、開発環境でも本番環境でも安定して動作するため、初心者から中級者まで幅広く利用されています。 以下では、まとめとして今回取り扱ったサンプルコードの要点をもう一度整理し、非同期処理の基本構造を理解しやすく示します。
サンプルコード(振り返り)
@app.route('/start-task', methods=['POST'])
def start_task():
data = request.get_json()
duration = data.get('duration', 5)
task = heavy_task.delay(duration)
return jsonify({'task_id': task.id, 'status': '受け付けました'})
@celery.task
def heavy_task(duration):
time.sleep(duration)
return f"{duration}秒の処理が完了しました"
このように、タスクをdelay()で実行するだけでバックグラウンド処理が可能になります。Flask側は最小限のコードで非同期化され、アプリケーションの応答性が向上します。タスクステータスの取得や結果の返却など、APIとして必要な機能も容易に追加できるため、実践的なWebアプリケーションにも適応しやすい構成です。非同期処理は、今後ますます多くのWebサービスで要求される技術であり、その基礎を身につけておくことで、よりスケーラブルで使いやすいサービス設計が可能になります。
生徒:「今日の内容で、FlaskのAPIがレスポンスを返す仕組みがよく分かりました。非同期処理って便利なんですね。」
先生:「そうですね。特にAPI開発では、重い処理を本体のレスポンスと切り離すことでユーザー体験を大きく改善できます。」
生徒:「Celeryって最初は難しそうに見えましたが、タスクを定義してdelay()で呼ぶだけで動くのは驚きました。」
先生:「実際に使うとシンプルでしょう?そのうえ、並列処理やスケジュールタスクなど応用範囲も広いので、学んでおく価値のあるライブラリですよ。」
生徒:「Redisもメッセージブローカーとして重要な役割をしているんですね。バックグラウンド処理って仕組みを知ると面白いです。」
先生:「理解が深まってきたようですね。これからはAPI設計の中で、どんな場面で非同期処理を使うべきか考えられるようになると良いですよ。」
生徒:「はい!次はメール送信や画像処理でも試してみたいです。」
先生:「いいですね。応用できる場面はたくさんあるので、ぜひ次のステップにも挑戦してみましょう。」