简体   繁体   中英

How to speed up JSON for a flask application?

I'm currently implementing a webapp in flask. It's an app that does a visualization of data gathered. Each page or section will always have a GET call and each call will return a JSON response which then will be processed into displayed data.

The current problem is that some calculation is needed before the function could return a JSON response. This causes some of the response to arrive slower than others and thus making the page loads a bit slow. How do I properly deal with this? I have read into caching in flask and wonder whether that is what the app need right now. I have also researched a bit into implementing a Redis-Queue. I'm not really sure which is the correct method.

Any help or insights would be appreciated. Thanks in advance

Here are some ideas:

If the source data that you use for your calculations is not likely to change often then you can run the calculations once and save the results. Then you can serve the results directly for as long as the source data remains the same.

You can save the results back to your database, or as you suggest, you can save them in a faster storage such as Redis. Based on your description I suspect the big performance gain will be in not doing calculations so often, the difference between storing in a regular database vs. Redis or similar is probably not significant in comparison.

If the data changes often then you will still need to do calculations frequently. For such a case an option that you have is to push the calculations to the client. Your Flask app can just return the source data in JSON format and then the browser can do the processing on the user's computer.

I hope this helps.

You can use copy_current_request_context and Redis, Thread

It is helpful when you need long time to make JSON response. The first request maybe slow, but next request will faster.

Example

from datetime import timedelta, datetime
from threading import Thread
from . import dbb, redis_client
from flask import Blueprint, request, jsonify, flash, after_this_request, copy_current_request_context, \
    current_app, send_from_directory
from .models import Shop, Customers
def save_customer_json_to_redis(request):
    response_json = {
        "have_customer": False,
        "status": False,
        "anythingelse": None,
        "message":"False, you have to check..."
    }
    #print(request.data)
    headers = request.headers
    Authorization = headers['Authorization']
    token = Authorization.replace("Bearer", "")
    phone = request.args.get('phone')
    if phone is not None and phone != "":
        print('token', token, "phone", phone)
        now = datetime.utcnow() + timedelta(hours=7)
        shop = Shop.query.filter(Shop.private_token == token, Shop.ended_date > now, Shop.shop_active == True).first()      
        customer = Customers.query.filter_by(shop_id=shop.id, phone=phone).first()
        if customer:
            redis_name = f'{shop.id}_api_v2_customer_phone_{phone}_customer_id_{customer.id}'
            print(redis_name)
            response_json["anythingelse"] = ...# do want you want, it need long time to do
            response_json["status"] = True
            response_json["message"] = "Successful"
            redis_client.set(redis_name, json.dumps(response_json)) #Save JSON to Redis
  
@app.route('/api/v2/customer', methods=['GET'])
def api_customer():
    @copy_current_request_context
    def do_update_customer_to_redis():# this function to save JSON you want to response next time to Redis
        save_customer_json_to_redis(request)
        
      
    Thread(target=do_update_customer_to_redis).start() 
    response_json = {
                  "have_customer": False,
                  "status": False,
                  "anythingelse": {},
                  "message": "False, you have to check..."
                  }
    
    #print(request.data)
    headers = request.headers
    Authorization = headers['Authorization']
    token = Authorization.replace("Bearer", "")
    phone = request.args.get('phone')
    if phone is not None and phone != "":
        print('token', token, "phone", phone)
        now = datetime.utcnow() + timedelta(hours=7)
        shop = Shop.query.filter(Shop.private_token == token, Shop.ended_date > now,Shop.shop_active == True).first()
        customer = Customers.query.filter_by(shop_id=shop.id, phone=phone).first()
        if customer:
            redis_name = f'{shop.id}_api_v2_customer_phone_{phone}_customer_id_{customer.id}'
            print(redis_name)
            try:
                response_json = json.loads(redis_client.get(redis_name)) # if have json from app
                print("json.loads(redis_client.get(redis_name))")
            except Exception as e:
                print("json.loads(redis_client.get(redis_name))", e)
                #do any thing you want to response json
                response_json["anythingelse"] = ...# do want you want, it need long time to do
                response_json["message"]= ...#do want you want
                #redis_client.set(redis_name, json.dumps(response_json))
                response_json["status"] = True
                response_json["message"] = "Successful"
   return jsonify(response_json)
                

In the init .py

from flask import Flask
from flask_cors import CORS
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy
from redis import Redis

# init SQLAlchemy so we can use it later in our models
dbb = SQLAlchemy(session_options={"autoflush": False})

redis_client = Redis(
    host='localhost',
    port='6379',
    password='your_redis_password'
)
def create_app():
    app = Flask(__name__)
    ...........

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM