Python Http request asynchronous return (multithreaded)

Posted by Richard Bowser on Tue, 25 Jan 2022 12:16:37 +0100

preface

Sometimes we may encounter such a situation. We have a function that provides an http interface. We need to send a request to the http interface to start the service, but the service function may be executed for a long time. In this way, if the request result is returned after the function is executed, the request may timeout.

client

import requests  
req = requests.get("http://127.0.0.1:9898/register?username=aaa&pwd=232323")
print(req.content)

Server

# coding=utf-8
import flask
from flask import jsonify
from flask import request

from gevent import pywsgi

import sys
reload(sys)
import time
sys.setdefaultencoding('utf-8')

server = flask.Flask(__name__)

@server.route('/register', methods=['get', 'post'])
def registerPost():
    # The post request obtains the parameters of the request, and the return result type is str
    username = request.values.get('username')
    pwd = request.values.get('pwd')
    app_id = request.values.get('app_id')
    dowork(app_id)
    # confirmpwd = request.values.get('confirmpwd')
    if username and pwd:  # Judge whether the user name, password and confirmation password entered are not empty
        return ("User name is:%s, Password is:%s" % (username, pwd))
    else:
        return jsonify({"code": 504, "msg": "Required item cannot be blank"})


if __name__ == '__main__':
    # Port can be specified. The default port is 5000
    # The default host is 127.0.0.1. If it is written as 0.0.0.0, others can access it, which means listening to multiple network cards,
    # server.run(debug=True, port=9898, host='0.0.0.0')
    server = pywsgi.WSGIServer(('0.0.0.0', 9898), server)
    server.serve_forever()

This is a typical synchronous return result. After the request is initiated, the request result can only be returned after the dowork() function is executed. If the dowork() execution time is long, the client request will timeout

At this time, we may need an asynchronous http interface. After receiving the request from the client, we will immediately return a request result, and then slowly execute the task to be executed. How to realize this process? My method is to realize it through multithreading. In the response function of the server, we will receive a request every time and obtain the parameters carried in the request, Then use these parameters to create a thread that will execute our function service, and finally return the request result, so that the client can quickly obtain the request result, so as not to make the client request timeout

The following is the response function of the server added with thread

# coding=utf-8
import flask
from flask import jsonify
from flask import request

from gevent import pywsgi

import sys
reload(sys)
import time
sys.setdefaultencoding('utf-8')

server = flask.Flask(__name__)

import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter, app_id):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.app_id = app_id
    def run(self):
        print ("Start thread:" + self.name)
        print_time(self.name, self.counter, 1, self.app_id)
        print ("Exit thread:" + self.name)

def print_time(threadName, delay, counter, app_id):
    while counter:
        if exitFlag:
            threadName.exit()
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        dowork(app_id)
        counter -= 1

@server.route('/register', methods=['get', 'post'])
def registerPost():
    # The post request obtains the parameters of the request, and the return result type is str
    username = request.values.get('username')
    pwd = request.values.get('pwd')
    app_id = request.values.get('app_id')

    # Create a new thread
    thread1 = myThread(1, "Thread-1", 1, app_id)
    # Start a new thread
    thread1.start()

    # confirmpwd = request.values.get('confirmpwd')
    if username and pwd:  # Judge whether the user name, password and confirmation password entered are not empty
        return ("User name is:%s, Password is:%s" % (username, pwd))
    else:
        return jsonify({"code": 504, "msg": "Required item cannot be blank"})


if __name__ == '__main__':
    # Port can be specified. The default port is 5000
    # The default host is 127.0.0.1. If it is written as 0.0.0.0, others can access it, which means listening to multiple network cards,
    # server.run(debug=True, port=9898, host='0.0.0.0')
    server = pywsgi.WSGIServer(('0.0.0.0', 9898), server)
    server.serve_forever()
Because the thread's run() method and start() method cannot pass parameters, if we need to obtain parameters from the request and pass them to the function to be executed, we can add the parameters we need to pass to the parameters of the thread's construction method, so that we can dynamically obtain the parameters passed in the request inside the run() method

Topics: Python Multithreading http