qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

          使用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è)試

          <2013年5月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類(lèi)

          隨筆檔案

          文章分類(lèi)

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 天津市| 琼中| 巍山| 宣恩县| 玉溪市| 沈阳市| 龙胜| 丰都县| 东海县| 宁陵县| 安岳县| 吴忠市| 云林县| 句容市| 淅川县| 洪湖市| 通山县| 上犹县| 廉江市| 武夷山市| 烟台市| 沙坪坝区| 巴东县| 虹口区| 平安县| 衢州市| 牙克石市| 蒙自县| 南陵县| 遂宁市| 神池县| 汝城县| 临猗县| 德化县| 和平区| 太仆寺旗| 竹山县| 遂平县| 荔浦县| 南澳县| 曲靖市|