如何在Flask中实现GET请求并行、POST/PUT/DELETE请求排队?
Absolutely! You can pull this off with Flask and Python. Even with threaded=True enabled (which lets Flask handle multiple requests at once via separate threads), you can enforce that POST/PUT/DELETE requests run sequentially (one after another) while GET requests keep processing in parallel. Here's a straightforward, effective approach:
Core Idea
Flask's threaded server spins up a new thread for each incoming request. By default, all threads run independently—this means concurrent write requests (POST/PUT/DELETE) could cause race conditions if they modify shared data. To fix this, we use a thread lock to ensure only one write operation runs at a time, while read requests (GET) skip the lock and run freely.
Step-by-Step Implementation
First, we'll use Python's built-in threading.Lock and a custom decorator to apply the lock to our write routes:
from flask import Flask, request import threading app = Flask(__name__) # Create a mutual exclusion lock for write operations write_lock = threading.Lock() # Decorator to enforce sequential execution for write routes def require_write_lock(f): def decorated_function(*args, **kwargs): # Acquire the lock before running the view function with write_lock: return f(*args, **kwargs) return decorated_function # GET requests run in parallel (no lock applied) @app.route('/data', methods=['GET']) def get_data(): # Your read-only logic here (e.g., fetch from database) return {"status": "success", "message": "GET processed in parallel"} # POST requests use the lock (sequential execution) @app.route('/data', methods=['POST']) @require_write_lock def post_data(): # Your write logic here (e.g., insert into database) return {"status": "success", "message": "POST processed sequentially"} # PUT requests also use the lock @app.route('/data/<int:id>', methods=['PUT']) @require_write_lock def update_data(id): # Your update logic here return {"status": "success", "message": f"PUT for {id} processed sequentially"} # DELETE requests follow the same rule @app.route('/data/<int:id>', methods=['DELETE']) @require_write_lock def delete_data(id): # Your delete logic here return {"status": "success", "message": f"DELETE for {id} processed sequentially"} if __name__ == '__main__': app.run(threaded=True)
How This Works
- Write Requests: The
with write_lockstatement ensures only one thread can execute the wrapped view function at a time. Any subsequent write requests will wait in a queue until the lock is released (when the current write operation finishes). - GET Requests: Since they don't use the lock, they can run concurrently with each other and even with an ongoing write request (safe for most read-only operations—if you need reads to wait for writes, you'd use a reader-writer lock instead, but that's a more advanced use case).
Notes for Scaling
- If you later switch to a multi-process WSGI server (like Gunicorn with multiple workers), this thread lock won't work across processes (each process has its own lock instance). For that scenario, you'd need a distributed lock (e.g., using Redis or a database to coordinate locks across processes).
- For long-running write operations, consider offloading them to a task queue (like Celery) with a single worker. This keeps Flask free to handle GET requests immediately while writes are queued and processed sequentially.
内容的提问来源于stack exchange,提问作者Jay

