簡體   English   中英

增加每秒的請求量

[英]Increase amounts of requests per second

我正在嘗試增加每秒的請求量。 我目前正在使用 python 2.7 並且能夠每秒獲得大約 1 個請求。 我需要多線程/多處理函數還是異步運行 func 的多個實例。 我不知道如何進行這項工作。 請幫忙 :-)

while True:
    r = requests.post(url, allow_redirects=False, data={
        str(formDataNameLogin): username,
        str(formDataNamePass): password,
    })

    print 'Sending username: %s with password %s' % (username, password)

只需使用任何異步庫。 我認為請求的異步版本,例如grequest 、 txrequests 、 requests-futures 和 requests-threads 最適合您。 下面是來自 grequests 的自述文件的代碼示例:

 import grequests urls = [ 'http://www.heroku.com', 'http://python-tablib.org', 'http://httpbin.org', 'http://python-requests.org', 'http://fakedomain/', 'http://kennethreitz.com' ]

創建一組未發送的請求:

 rs = (grequests.get(u) for u in urls)

同時發送它們:

 grequests.map(rs)

使用或學習其他提到的模塊,比如請求線程,可能會稍微涉及更多,尤其是使用 python 2

from twisted.internet.defer import inlineCallbacks
from twisted.internet.task import react
from requests_threads import AsyncSession

session = AsyncSession(n=100)

@inlineCallbacks
def main(reactor):
    responses = []
    for i in range(100):
        responses.append(session.get('http://httpbin.org/get'))

    for response in responses:
        r = yield response
        print(r)

if __name__ == '__main__':
    react(main)

asyncioaiohttp可能更值得注意,但是,我想,學習一個已經熟悉的模塊的版本會更容易。

多線程是不必要的,但你可以嘗試mutithreading或者,甚至更好,multiptrocessing,看看哪一種最適合。

您可以使用多線程執行多個並行請求:

import Queue
import threading
import time
import requests

exit_flag = 0

class RequestThread(threading.Thread):
    def __init__(self, thread_id, name, q):
        threading.Thread.__init__(self)
        self.thread_id = thread_id
        self.name = name
        self.q = q
    def run(self):
        print("Starting {0:s}".format(self.name))
        process_data(self.name, self.q)
        print("Exiting {0:s}".format(self.name))

def process_data(thread_name, q):
    while not exit_flag:
        queue_lock.acquire()
        if not qork_queue.empty():
            data = q.get()
            queue_lock.release()
            print("{0:s} processing {1:s}".format(thread_name, data))
            response = requests.get(data)
            print(response)
        else:
            queue_lock.release()
        time.sleep(1)

thread_list = ["Thread-1", "Thread-2", "Thread-3"]
request_list = [
    "https://api.github.com/events",
    "http://api.plos.org/search?q=title:THREAD",
    "http://api.plos.org/search?q=title:DNA",
    "http://api.plos.org/search?q=title:PYTHON",
    "http://api.plos.org/search?q=title:JAVA"
]
queue_lock = threading.Lock()
qork_queue = Queue.Queue(10)
threads = []
thread_id = 1

# Create new threads
for t_name in thread_list:
    thread = RequestThread(thread_id, t_name, qork_queue)
    thread.start()
    threads.append(thread)
    thread_id += 1

# Fill the queue
queue_lock.acquire()
for word in request_list:
    qork_queue.put(word)
queue_lock.release()

# Wait for queue to empty
while not qork_queue.empty():
    pass

# Notify threads it's time to exit
exit_flag = 1

# Wait for all threads to complete
for t in threads:
    t.join()

print("Exiting Main Thread")

輸出:

Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-1 processing https://api.github.com/events
Thread-2 processing http://api.plos.org/search?q=title:THREAD
Thread-3 processing http://api.plos.org/search?q=title:DNA
<Response [200]>
<Response [200]>
<Response [200]>
Thread-2 processing http://api.plos.org/search?q=title:PYTHON
Thread-3 processing http://api.plos.org/search?q=title:JAVA
Exiting Thread-1
<Response [200]>
<Response [200]>
Exiting Thread-3
Exiting Thread-2
Exiting Main Thread

盡管我不是多線程專家,但還是要稍微解釋一下:

1.隊列

Queue模塊允許您創建一個新的隊列對象,該對象可以容納特定數量的項目。 有以下方法來控制隊列:

  • get() - 從隊列中刪除並返回一個項目。
  • put() - 將一個項目添加到隊列中。 qsize() - 返回當前在隊列中的項目數。
  • empty() - 如果隊列為空,則返回 True; 否則為 False。
  • full() - 如果隊列已滿,則返回 True; 否則,為假。

對於我在多線程方面的一點經驗,這對於控制您仍然需要處理的數據很有用。 我遇到過線程在做同樣的事情或者除了一個之外所有線程都退出的情況。 這幫助我控制要處理的共享數據。

2.鎖

Python 提供的線程模塊包括一個易於實現的 鎖定機制,允許您同步線程。 通過調用Lock()方法創建一個新鎖,該方法返回新鎖。

原始鎖處於“鎖定”或“解鎖”兩種狀態之一。 它是在解鎖狀態下創建的。 它有兩個基本方法,acquire() 和 release()。 當狀態解鎖時,acquire() 將狀態更改為鎖定並立即返回。 當狀態被鎖定時,acquire() 會阻塞,直到另一個線程中對 release() 的調用將其更改為解鎖狀態,然后acquire() 調用將其重置為鎖定狀態並返回。 release() 方法只能在鎖定狀態下調用; 它將狀態更改為解鎖並立即返回。 如果嘗試釋放未鎖定的鎖,則會引發 ThreadError。

對更人性化的語言鎖是線程模塊提供的最基本的同步機制。 在任何時候,一個鎖都可以被一個線程持有,或者根本沒有線程持有。 如果一個線程試圖持有一個已經被其他線程持有的鎖,第一個線程的執行將暫停,直到該鎖被釋放。

鎖通常用於同步對共享資源的訪問。 對於每個共享資源,創建一個 Lock 對象。 當你需要訪問資源時,調用acquire來持有鎖(這會等待鎖被釋放,如果需要的話),然后調用release來釋放它。

3.線程

要使用 threading 模塊實現新線程,您必須執行以下操作:

  • 定義 Thread 類的新子類。
  • 覆蓋init (self [,args]) 方法以添加其他參數。
  • 然后,重寫 run(self [,args]) 方法來實現線程在啟動時應該做什么。

一旦創建了新的 Thread 子類,就可以創建它的一個實例,然后通過調用 start() 啟動一個新線程,然后調用 run() 方法。 方法:

  • run() - 方法是線程的入口點。
  • start() - 方法通過調用 run 方法啟動一個線程。
  • join([time]) - 等待線程終止。
  • isAlive() - 方法檢查線程是否仍在執行。
  • getName() - 返回線程的名稱。
  • setName() - 設置線程的名稱。

真的更快嗎?

使用單線程:

$ time python single.py 
Processing request url: https://api.github.com/events
<Response [200]>
Processing request url: http://api.plos.org/search?q=title:THREAD
<Response [200]>
Processing request url: http://api.plos.org/search?q=title:DNA
<Response [200]>
Processing request url: http://api.plos.org/search?q=title:PYTHON
<Response [200]>
Processing request url: http://api.plos.org/search?q=title:JAVA
<Response [200]>
Exiting Main Thread

real    0m22.310s
user    0m0.096s
sys 0m0.022s

使用 3 個線程:

Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-3 processing https://api.github.com/events
Thread-1 processing http://api.plos.org/search?q=title:THREAD
Thread-2 processing http://api.plos.org/search?q=title:DNA
<Response [200]>
<Response [200]>
<Response [200]>
Thread-1 processing http://api.plos.org/search?q=title:PYTHON
Thread-2 processing http://api.plos.org/search?q=title:JAVA
Exiting Thread-3
<Response [200]>
<Response [200]>
Exiting Thread-1
 Exiting Thread-2
Exiting Main Thread

real    0m11.726s
user    0m6.692s
sys 0m0.028s

使用 5 個線程:

time python multi.py 
Starting Thread-1
Starting Thread-2
Starting Thread-3
 Starting Thread-4
Starting Thread-5
Thread-5 processing https://api.github.com/events
Thread-1 processing http://api.plos.org/search?q=title:THREAD
Thread-2 processing http://api.plos.org/search?q=title:DNA
Thread-3 processing http://api.plos.org/search?q=title:PYTHONThread-4 processing http://api.plos.org/search?q=title:JAVA

<Response [200]>
<Response [200]>
 <Response [200]>
<Response [200]>
<Response [200]>
Exiting Thread-5
Exiting Thread-4
Exiting Thread-2
Exiting Thread-3
Exiting Thread-1
Exiting Main Thread

real    0m6.446s
user    0m1.104s
sys 0m0.029s

5 個線程幾乎快 4 倍。 這些只是大約 5 個虛擬請求。 想象一下更大的數據塊。

請注意:我只在 python 2.7 下測試過,對於 python 3.x 可能需要進行小幅調整。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM