1. 程式人生 > 實用技巧 >python利用多執行緒讓http請求非同步返回

python利用多執行緒讓http請求非同步返回

有時我們可能會碰到這樣一種情況,我們有一個功能,這個功能對外提供了一個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
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請求獲取請求的引數,返回結果型別是str
18 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()
這個就是一個典型的同步返回結果,發起請求後,必須等 dowork() 功能執行完之後才能返回請求結果,如果 dowork() 執行時間較長,則會導致客戶端請求超時 這時我們可能就需要一個非同步的http介面,收到客戶端的請求後,馬上返回一個請求結果,然後再慢慢的執行要執行的任務,這個過程怎麼實現呢,我的做法是通過多執行緒來實現,在服務端的響應函式中,每次收到一個請求,獲取請求中攜帶的引數,然後用這些引數建立一個會執行我們功能服務的執行緒,最後返回請求結果,這樣客戶端可以很快獲取到請求結果,從而不會讓客戶端請求超時 下面是加入了執行緒的服務端的響應函式
 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()方法內部我們就能動態獲得請求中傳遞的引數了