python利用多執行緒讓http請求非同步返回
阿新 • • 發佈:2020-09-06
有時我們可能會碰到這樣一種情況,我們有一個功能,這個功能對外提供了一個http介面,我們需要對這個http介面發起請求才能啟動這個服務,但是這個服務功能可能會執行很久,這樣如果等功能執行結束再返回請求結果,那這個請求可能就超時了,
發起請求的客戶端
1 import requests 2 3 req = requests.get("http://127.0.0.1:9898/register?username=aaa&pwd=232323") 4 print(req.content)服務端
1 # coding=utf-8 2 import flask 3 from flask import這個就是一個典型的同步返回結果,發起請求後,必須等 dowork() 功能執行完之後才能返回請求結果,如果 dowork() 執行時間較長,則會導致客戶端請求超時 這時我們可能就需要一個非同步的http介面,收到客戶端的請求後,馬上返回一個請求結果,然後再慢慢的執行要執行的任務,這個過程怎麼實現呢,我的做法是通過多執行緒來實現,在服務端的響應函式中,每次收到一個請求,獲取請求中攜帶的引數,然後用這些引數建立一個會執行我們功能服務的執行緒,最後返回請求結果,這樣客戶端可以很快獲取到請求結果,從而不會讓客戶端請求超時 下面是加入了執行緒的服務端的響應函式jsonify 4 from flask import request 5 6 from gevent import pywsgi 7 8 import sys 9 reload(sys) 10 import time 11 sys.setdefaultencoding('utf-8') 12 13 server = flask.Flask(__name__) 14 15 @server.route('/register', methods=['get', 'post']) 16 def registerPost(): 17 # post請求獲取請求的引數,返回結果型別是str18 username = request.values.get('username') 19 pwd = request.values.get('pwd') 20 app_id = request.values.get('app_id') 21 dowork(app_id) 22 # confirmpwd = request.values.get('confirmpwd') 23 if username and pwd: # 判斷輸入的使用者名稱、密碼、確認密碼都不為空 24 return ("使用者名稱為:%s, 密碼為:%s" % (username, pwd)) 25 else: 26 return jsonify({"code": 504, "msg": "必填項不能為空"}) 27 28 29 if __name__ == '__main__': 30 # port可以指定埠,預設埠是5000 31 # host預設是127.0.0.1,寫成0.0.0.0的話,其他人可以訪問,代表監聽多塊網絡卡上面, 32 # server.run(debug=True, port=9898, host='0.0.0.0') 33 server = pywsgi.WSGIServer(('0.0.0.0', 9898), server) 34 server.serve_forever()
1 # coding=utf-8 2 import flask 3 from flask import jsonify 4 from flask import request 5 6 from gevent import pywsgi 7 8 import sys 9 reload(sys) 10 import time 11 sys.setdefaultencoding('utf-8') 12 13 server = flask.Flask(__name__) 14 15 import threading 16 import time 17 18 exitFlag = 0 19 20 class myThread (threading.Thread): 21 def __init__(self, threadID, name, counter, app_id): 22 threading.Thread.__init__(self) 23 self.threadID = threadID 24 self.name = name 25 self.counter = counter 26 self.app_id = app_id 27 def run(self): 28 print ("開始執行緒:" + self.name) 29 print_time(self.name, self.counter, 1, self.app_id) 30 print ("退出執行緒:" + self.name) 31 32 def print_time(threadName, delay, counter, app_id): 33 while counter: 34 if exitFlag: 35 threadName.exit() 36 time.sleep(delay) 37 print ("%s: %s" % (threadName, time.ctime(time.time()))) 38 dowork(app_id) 39 counter -= 1 40 41 @server.route('/register', methods=['get', 'post']) 42 def registerPost(): 43 # post請求獲取請求的引數,返回結果型別是str 44 username = request.values.get('username') 45 pwd = request.values.get('pwd') 46 app_id = request.values.get('app_id') 47 48 # 建立新執行緒 49 thread1 = myThread(1, "Thread-1", 1, app_id) 50 # 開啟新執行緒 51 thread1.start() 52 53 # confirmpwd = request.values.get('confirmpwd') 54 if username and pwd: # 判斷輸入的使用者名稱、密碼、確認密碼都不為空 55 return ("使用者名稱為:%s, 密碼為:%s" % (username, pwd)) 56 else: 57 return jsonify({"code": 504, "msg": "必填項不能為空"}) 58 59 60 if __name__ == '__main__': 61 # port可以指定埠,預設埠是5000 62 # host預設是127.0.0.1,寫成0.0.0.0的話,其他人可以訪問,代表監聽多塊網絡卡上面, 63 # server.run(debug=True, port=9898, host='0.0.0.0') 64 server = pywsgi.WSGIServer(('0.0.0.0', 9898), server) 65 server.serve_forever()
因為執行緒的run()方法和start()方法是不能傳遞引數的,所以如果我們需要從請求中獲取引數然後傳遞給要執行的功能的話,可以線上程的構造方法的引數中加上我們需要傳遞的引數,這樣在run()方法內部我們就能動態獲得請求中傳遞的引數了