2014-10-30 1 views
0

я создаю веб-сервис CherryPy, который хранит данные в карте, получает ключ от клиентов и возвращает соответствующий данные:Создание нескольких запросов, чтобы получить данные из веб-службы CherryPy

import sys 
import imp 
import cherrypy 

data_source = get_data() # get data from the database and store it in the map 

class Provider: 
    exposed = True 

    def POST(self, key): 
     global data_source 
     data = data_source[key] # get stored data based on given key 
     return data 

if __name__ == '__main__': 
    cherrypy.tree.mount(Provider(), '/Provider',{'/': 
      {'request.dispatch': cherrypy.dispatch.MethodDispatcher()} 
     }) 
    cherrypy.config.update({'server.socket_host': '0.0.0.0', 
      'server.socket_port': 8080, 
     }) 
    cherrypy.server.max_request_body_size = 1048576000 
    cherrypy.engine.start() 
    cherrypy.engine.block() 

Затем на другой машине , Я создаю скрипт для запроса данных от поставщика. Использование сценария, можно scpecify, сколько одновременных запросов, что я хочу сделать:

import requests 
import time 
from threading import Thread 

def make_request(id, key): 
    start = time.time() 
    r = requests.post("http://provider-host/Provider", {'key':key}) 
    end = time.time() 
    print 'Thread {0} takes {1} seconds to finish with status code {2}'.format(id, end - start, r.status_code) 

def start(num, key): 
    ts = [] 
    for i in range(num): 
     t = Thread(target=make_request, args=(i, key)) 
     ts.append(t) 
    for t in ts: t.start() 
    for t in ts: t.join() 

Наконец, я делаю тест, чтобы запросить одни и те же ключевые в 10 раз, с 2-мя различными способами: последовательный и параллельный.

Последовательный метод:

time for i in range(10): start(1, 'big_data_key') 

В результате:

Thread 0 takes 2.51558494568 seconds to finish with status code 200 
Thread 0 takes 2.47761011124 seconds to finish with status code 200 
Thread 0 takes 2.66229009628 seconds to finish with status code 200 
Thread 0 takes 2.47381901741 seconds to finish with status code 200 
Thread 0 takes 2.4907720089 seconds to finish with status code 200 
Thread 0 takes 2.93357181549 seconds to finish with status code 200 
Thread 0 takes 2.47671484947 seconds to finish with status code 200 
Thread 0 takes 2.40888786316 seconds to finish with status code 200 
Thread 0 takes 2.6319899559 seconds to finish with status code 200 
Thread 0 takes 2.77075099945 seconds to finish with status code 200 
CPU times: user 1.79 s, sys: 1.06 s, total: 2.85 s 
Wall time: 25.9 s 

Параллельные методы:

time start('138.251.195.251', 10, 'big_data_key') 

В результате получается:

Thread 5 takes 15.5736939907 seconds to finish with status code 200 
Thread 1 takes 19.4057281017 seconds to finish with status code 200 
Thread 7 takes 21.4743158817 seconds to finish with status code 200 
Thread 8 takes 22.4408829212 seconds to finish with status code 200 
Thread 0 takes 24.1915988922 seconds to finish with status code 200 
Thread 2 takes 24.3175201416 seconds to finish with status code 200 
Thread 6 takes 24.3368370533 seconds to finish with status code 200 
Thread 4 takes 24.3618791103 seconds to finish with status code 200 
Thread 9 takes 24.3891952038 seconds to finish with status code 200 
Thread 3 takes 24.5536601543 seconds to finish with status code 200 
CPU times: user 2.34 s, sys: 1.67 s, total: 4.01 s 
Wall time: 24.6 s 

Понятно, что с использованием параллельного метода время, необходимое для завершения одного запроса, выше, чем в последовательном методе.

Итак, мой вопрос заключается в следующем: разница в времени загрузки, вызванная пропускной способностью между двумя машинами или чем-то еще, например. вишневый? Если это вызвано чем-то другим, я был бы признателен за любые предложения по его устранению.

+0

Расскажите нам о размере '' big_data_key'' и '' large_text.txt''. И о средней пропускной способности (например, '' wget'' некоторый большой файл) вашего сетевого соединения между машинами. Затем вы можете выполнить математику ожидаемых таймингов для последовательного и параллельного корпуса. – saaj

+0

привет, я исправил свой вопрос, чтобы использовать только один ключ. Размер данных - 22 Мб, а пропускная способность - 10,8 мб/с. –

ответ

1

Тогда ясно, что ваше узкое место - это сеть. Имея 220MiB для передачи при 10,8MiB/s, требуется не менее 20 секунд. Вы эксперимент занимает ~ 25 секунд, что составляет 8,8 Мбайт/с, то есть эффективная ~ 74 Мбит/с из 100 Мбит/с максимальной теоретической емкости. Это хороший результат, учитывая все возможные ошибки измерения.

Разница между последовательным и параллельным корпусом (~ 5%) показывает, что мультиплексирование не помогает, поскольку узким местом является пропускная способность сети, а не индивидуальное ограничение связи.

Чтобы измерить влияние CherryPy, вы можете настроить веб-сервер, написанный на собственном коде, я предлагаю nginx, поместите туда файл и попробуйте скачать его 10 раз. Для параллельного теста вы можете попробовать Apache ab, например ab -n 10 -c 10 http://provider-host/some-big-file.

также несколько примечаний о CherryPy:

  • CherryPy представляет собой резьбовой сервер по умолчанию пул потоков, server.thread_pool, имеет 10 рабочих,
  • Попытка активировать сжатие GZIP, '/' : {'tools.gzip.on': True}, в вашей конфигурации, который будет дают существенный импульс для текстовых данных.

Вы также можете посмотреть this question, о обработке больших файлов с помощью CherryPy.