1 миллион заданий каждую минуту с использованием python-eventlet

Вариант использования:

  1. Чтение данных с одного сервера
  2. Манипулировать на моем сервере
  3. Отправить данные на другой сервер

Но требуется пропускная способность 1 миллион в минуту.

Больше объяснений: -

Предположим, что существует 10000 клиентов, и для клиента мне нужно вызвать 5 API и обработать данные в ответ, и после манипуляции будет создано около 30 API. И я хочу отправить данные на другой сервер.

(Предположение: сервер, с которого получение данных для вызова API занимает 250 мс, а сервер, на котором я публикую данные, занимает 350 мс для данных POST для вызова API.)

Псевдокод:

In every minute For each customers( there are 10000 customers):


Fetch data from first_server_for_first_service
Fetch data from first_server_for_second_service
Fetch data from first_server_for_third_service
Fetch data from first_server_for_fourth_service
Fetch data from first_server_for_fifth_service

Manipulate data of first_service
Manipulate data of second_service
Manipulate data of third_service
Manipulate data of fourth_service
Manipulate data of fifth_service

post data to second_server_for_first_service_1_type
post data to second_server_for_first_service_2_type
post data to second_server_for_first_service_3_type
post data to second_server_for_first_service_4_type
post data to second_server_for_first_service_5_type
post data to second_server_for_first_service_6_type
post data to second_server_for_second_service_1_type
post data to second_server_for_second_service_2_type
post data to second_server_for_second_service_3_type
post data to second_server_for_second_service_4_type
post data to second_server_for_second_service_5_type
post data to second_server_for_second_service_6_type
post data to second_server_for_third_service_1_type
post data to second_server_for_third_service_2_type
post data to second_server_for_third_service_3_type
post data to second_server_for_third_service_4_type
post data to second_server_for_third_service_5_type
post data to second_server_for_third_service_6_type
post data to second_server_for_fourth_service_1_type
post data to second_server_for_fourth_service_2_type
post data to second_server_for_fourth_service_3_type
post data to second_server_for_fourth_service_4_type
post data to second_server_for_fourth_service_5_type
post data to second_server_for_fourth_service_6_type
post data to second_server_for_fifth_service_1_type
post data to second_server_for_fifth_service_2_type
post data to second_server_for_fifth_service_3_type
post data to second_server_for_fifth_service_4_type
post data to second_server_for_fifth_service_5_type
post data to second_server_for_fifth_service_6_type

Как мы можем написать код через Eventlet, чтобы он мог выполнять столько задач параллельно. Или eventlet сможет выполнять эти многочисленные задачи?

Ответьте, пожалуйста.


person Anurag    schedule 07.01.2014    source источник
comment
Я не думаю, что eventlet вам поможет, так как он только распределит нагрузку, а не уменьшит ее. Если вы не можете получить желаемую производительность, вам нужно либо задействовать больше аппаратных ресурсов (предположительно сетевых, так как это, вероятно, узкое место) и использовать многопоточность, либо найти способ перепроектировать вашу систему, чтобы уменьшить количество хиты.   -  person aquavitae    schedule 07.01.2014


Ответы (1)


Краткий ответ: это жесткое требование. Если совсем не можете снизить нагрузку, настоятельно рекомендую присмотреться к быстрым языкам со встроенной поддержкой параллелизма: Go, Haskell, Ocaml. PyPy также должен помочь в этом случае.

10000 * 35 = 350 тысяч вызовов API в минуту. ~6К в секунду. Предполагая время отклика 350 мс, вам потребуется ~ 2100 подключений к вышестоящим и нижестоящим службам вместе, чтобы не отставать. Eventlet может без проблем разместить такое количество зеленых потоков.

Но тогда у вас большие проблемы с процессором. Наименьшие накладные расходы событий, которые я измерил на старом процессоре Core 2 Duo, составляют ~25 мкс. И у вас есть только 166 мкс (1 секунда / 6K операций) для каждого вызова. Удачи в полезной обработке данных за 140 мкс в Python. Хорошая новость заключается в том, что вы должны иметь возможность обрабатывать каждую, скажем, 1000 клиентов в отдельном процессе и распределять нагрузку ЦП на 10 ядер.

Для решения этой задачи с помощью Eventlet не потребуется никакого особенно интересного кода. Пример кода ниже, вероятно, самый простой из возможных способов. Ваши вызовы API должны иметь возможность повторно использовать существующие соединения сокетов. Вы можете захотеть добавить ограничения параллелизма или пропускной способности, используя очереди или семафоры.

clients = ['client1', 'client2', ...] # 10K


def service1(request):
    data1 = API.get()
    data2 = process(data1)
    eventlet.spawn(API.post_type_1, data2)
    eventlet.spawn(API.post_type_2, data2)
    # ...


def tick():
    now = time.time()
    for client in clients:
        # some context object
        request = (client, now)

        eventlet.spawn(service1, request)
        eventlet.spawn(service2, request)
        eventlet.spawn(service3, request)
        eventlet.spawn(service4, request)
        eventlet.spawn(service5, request)


def main():
    while True:
        tick()
        eventlet.sleep(60)
person temoto    schedule 08.01.2014
comment
Я использовал celery-eventlet. И это работает хорошо для меня. - person Anurag; 10.01.2014