使用Twisted Python和Treq進(jìn)行HTTP壓力測(cè)試
從事API相關(guān)的工作很有挑戰(zhàn)性,在高峰期保持系統(tǒng)的穩(wěn)定及健壯性就是其中之一,這也是我們?cè)贛ailgun做很多壓力測(cè)試的原因。
這么久以來(lái),我們已經(jīng)嘗試了很多種方法,從簡(jiǎn)單的ApacheBench到復(fù)雜些的自定義測(cè)試套。但是本貼講述的,是一種使用python進(jìn)行“快速粗糙”卻非常靈活的壓力測(cè)試的方法。
使用python寫(xiě)HTTP客戶(hù)端的時(shí)候,我們都很喜歡用 Requests library。這也是我們向我們的API用戶(hù)們推薦的。Requests 很強(qiáng)大,但有一個(gè)缺點(diǎn),它是一個(gè)模塊化的每線(xiàn)程一個(gè)調(diào)用的東西,很難或者說(shuō)不可能用它來(lái)快速的產(chǎn)生成千上萬(wàn)級(jí)別的請(qǐng)求。
Treq on Twisted簡(jiǎn)介
為解決這個(gè)問(wèn)題我們引入了Treq(Github庫(kù))。Treq是一個(gè)HTTP客戶(hù)端庫(kù),受Requests影響,但是它運(yùn)行在Twisted上,具有Twisted典型的強(qiáng)大能力:處理網(wǎng)絡(luò)I/O時(shí)它是異步且高度并發(fā)的方式。
Treq并不僅僅限于壓力測(cè)試:它是寫(xiě)高并發(fā)HTTP客戶(hù)端的好工具,比如網(wǎng)頁(yè)抓取。Treq很優(yōu)雅、易于使用且強(qiáng)大。這是一個(gè)例子:
>>> from treq import get >>> def done(response): ... print response.code ... reactor.stop() >>> get("http://www.github.com").addCallback(done) >>> from twisted.internet import reactor >>> reactor.run() 200 |
簡(jiǎn)單的測(cè)試腳本
如下是一個(gè)使用Treq的簡(jiǎn)單腳本,用最大可能量的請(qǐng)求來(lái)對(duì)單一URL進(jìn)行轟炸。
#!/usr/bin/env python from twisted.internet import epollreactor epollreactor.install() from twisted.internet import reactor, task from twisted.web.client import HTTPConnectionPool import treq import random from datetime import datetime req_generated = 0 req_made = 0 req_done = 0 cooperator = task.Cooperator() pool = HTTPConnectionPool(reactor) def counter(): '''This function gets called once a second and prints the progress at one second intervals. ''' print("Requests: {} generated; {} made; {} done".format( req_generated, req_made, req_done)) # reset the counters and reschedule ourselves req_generated = req_made = req_done = 0 reactor.callLater(1, counter) def body_received(body): global req_done req_done += 1 def request_done(response): global req_made deferred = treq.json_content(response) req_made += 1 deferred.addCallback(body_received) deferred.addErrback(lambda x: None) # ignore errors return deferred def request(): deferred = treq.post('http://api.host/v2/loadtest/messages', auth=('api', 'api-key'), data={'from': 'Loadtest <test@example.com>', 'to':'to@example.org', 'subject': "test"}, pool=pool) deferred.addCallback(request_done) return deferred def requests_generator(): global req_generated while True: deferred = request() req_generated += 1 # do not yield deferred here so cooperator won't pause until # response is received yield None if __name__ == '__main__': # make cooperator work on spawning requests cooperator.cooperate(requests_generator()) # run the counter that will be reporting sending speed once a second reactor.callLater(1, counter) # run the reactor reactor.run() |
輸出結(jié)果:
2013-04-25 09:30 Requests: 327 generated; 153 sent; 153 received 2013-04-25 09:30 Requests: 306 generated; 156 sent; 156 received 2013-04-25 09:30 Requests: 318 generated; 184 sent; 154 received |
“Generated”類(lèi)的數(shù)字代表被Twisted反應(yīng)器準(zhǔn)備好但是還沒(méi)有發(fā)送的請(qǐng)求。這個(gè)腳本為了簡(jiǎn)潔性忽略了所有錯(cuò)誤處理。為它添加超時(shí)狀態(tài)的信息就留給讀者作為一個(gè)練習(xí)。
這個(gè)腳本可以當(dāng)做是一個(gè)起始點(diǎn),你可以通過(guò)拓展改進(jìn)它來(lái)自定義特定應(yīng)用下的處理邏輯。建議你在改進(jìn)的時(shí)候用 collections.Counter 來(lái)替代丑陋的全局變量。這個(gè)腳本運(yùn)行在單線(xiàn)程上,想通過(guò)一臺(tái)機(jī)器壓榨出最大量的請(qǐng)求的話(huà),你可以用類(lèi)似 mulitprocessing 的技術(shù)手段。
愿你樂(lè)在壓力測(cè)試!
本文出自:http://www.oschina.net/translate/stress-testing-http-with-twisted-python-and-treq
posted on 2013-05-10 09:30 順其自然EVO 閱讀(280) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): 性能測(cè)試