LINUX.ORG.RU

Как быстро кидать много http запросов асинхронно?

 , , ,


1

3

Сейчас вот такой код используется:

from aiohttp import ClientSession

async def post(semaphore: asyncio.Semaphore, session: ClientSession, url: str, data: str):
    async with semaphore:
        try:
            async with session.post(url, data=data) as r:
                response_data = await r.read()

                class Response(object):
                    def __init__(self, status_code, text):
                        self.status_code = status_code
                        self.text = text

                return Response(r.status, response_data.decode('utf-8'))
        except Exception as e:
            print(e)
            return None


...................................
async with ClientSession() as session:
    semaphore = asyncio.Semaphore(256)
    coros = [post(semaphore, session, r[0], r[1]) for r in requests]
    requests = await asyncio.gather(*coros)

Но он показывает плохие результаты. Как можно ускорить и правильно ли я вообще делаю? Мне надо отправлять http запросы на сервер, но не более, чем 256 одновременно.

Ответ на: комментарий от Rastafarra

поверхностный гуглеж показал что тут применяются легкие потоки (или их имитация) которых в жабе нет, отакто

Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Rastafarra

Может, все на асме еще замутить? Есть действующий проект, нужна оптимизация, но не перевод на другой ЯП.

panter_dsd ★★★★ ()
Ответ на: комментарий от Rastafarra

акторы это концепция а не реализация, а каждая конкретная реализация имеет набор костылей который легко обламывается блокирующим вызовом

Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от ei-grad

Просадка на отправке идет. Логика такая: я беру из БД очередные 5К записей, разбиваю их на запросы (по определенной логике), отправляю эти запросы и удаляю из БД те записи, которые корректно отправились. На сервере (куда я отправляю) в это время количество коннектов одновременных держится в районе 150. В итоге, у меня в БД очередь копится.

panter_dsd ★★★★ ()
Ответ на: комментарий от panter_dsd

Вот на локальной машине на локальный сервак, на сервере Elapsed держится в районе 14 secs.

2017-01-27 14:13:34,500 [DEBUG] root: Load events from database. Elapsed 0 sec (http_retranslator.py:69)
2017-01-27 14:13:34,500 [DEBUG] root: Begin retranslate (http_retranslator.py:70)
2017-01-27 14:13:34,962 [DEBUG] root: Send all prepared requests (http_retranslator.py:111)
2017-01-27 14:13:37,750 [DEBUG] root: Remove all sent events (http_retranslator.py:118)
2017-01-27 14:13:37,910 [DEBUG] root: Retranslated 5000 records. Elapsed 3 secs (http_retranslator.py:125)
2
panter_dsd ★★★★ ()
Ответ на: комментарий от panter_dsd

Почему ты считаешь что проблема в отправке? Для меня пока совсем не очевидно, из того что ты написал. Скорее в сеть где-то упирается, или просто сервак тормозит, не? Пробовал меньше / больше параллельных запросов разрешать?

ei-grad ★★★★★ ()
Ответ на: комментарий от panter_dsd

Вот на локальной машине на локальный сервак, на сервере Elapsed держится в районе 14 secs.

Посмотри в сторону

  • исчерпания локальных портов (netstat -ntp | grep TIME_WAIT | wc -l)
  • conntrack-а, google тебе в помощь
  • проблем с резолвингом
  • возможно strace тебе что-то дельное покажет
kawaii_neko ★★★★ ()

в код особо не вникал, но нахер тебе семафоры? почему не запускаешь 256 запросов просто? синхронизация всегда ботлнек в конкурентных алгоритмах.

anonymous ()
Ответ на: комментарий от anonymous

У меня 5000 записей, из них формируется n реквестов, причем n около 4000-45000. Но сервак нельзя грузить, он принимает одновременно 256 подключений, не больше.

panter_dsd ★★★★ ()
Ответ на: комментарий от panter_dsd

Ну, ты его хотя бы так поставь и запусти, посмотри есть ли разница и насколько она значительна.

BigAlex ★★★ ()

Ужас какой :(

Perl5 и AnyEvent::HTTP делает это в миллиард раз удобнее и читабельнее.

DRVTiny ★★★★★ ()

Так секундочку я не понимаю. Вроде тут сидят господы с присутствующим головным мозгом. Почему никто ещё не сказал об телепатах на курорте? Этож просто на лицо.

Трейс любого питоновского профайлера в студию. Трейс сетевых подключений тоже (можно закопипастить маленький кусок одного подключения), сними wireshark или любым другим удобным инструментом. Как лечить болезнь не делая анализов? А вообще я предполагаю что выполнив первые 2 пункта ты и сам разберёщся в проблеме.

novoxudonoser ()
Ответ на: комментарий от novoxudonoser

Блин классная uvloop штука

Похоже на то, всё никак не соберусь сам его погонять и потестировать. Кстати, если интересно, обрати внимание на sanic — это веб-фреймворк, который пытается копиррровать api flask'а, но построен поверх uvloop.

grazor ()
Ответ на: комментарий от grazor

о, не мог название вспомнить. да забавная штука, но мимикрия с асинхронщиной хуе дружат. лучше торнадо или альбатрос как-то.

anonymous ()

Создать 250 pthread нитей, а потом, когда они уже будут созданы запустить в них запросы.

Dron ★★★★★ ()

так а во что упирается-то? Питон жрёт ~100%? Нет ли затыков на том сервере куда ты шлёшь запросы?

true_admin ★★★★★ ()
Ответ на: комментарий от Dron

не на питоне, но я обычно создаю N воркер тредов а потом туда пулю задания. С таким нехитрым алгоритмом, я чуть не уложил большой коорпоративный биллинг со слабого сервачка :)

mrdeath ★★★★★ ()
Ответ на: комментарий от ei-grad

Жабы не в тренде уже, надо брать модного суслика.

Недавно модный суслик уже не модный. В топе теперь язык «Рога и Копыта», на втором месте «Бобер»)

anonymous ()

Как можно ускорить и правильно ли я вообще делаю?

Чо в питон профайлер не завезли что-ли? И да, выглядит просто ужасно, даже не пыхе было бы лучше.

no-such-file ★★★★★ ()

Там либо ClientSession блокирует лишнего, либо сервер дохнет. Попробуй сначала запрсы на быстрый сервер поотсылать. Если будет быстро, тогда можно просто создавать новый ClientSession на каждый запрос.

redixin ★★★★ ()
Ответ на: комментарий от true_admin

Жрет в районе 20%. С сервером все отлично, сервис на c++ засылает на него данные в районе 250 запросов в секунду, пайтоновский - 100 запросов.

panter_dsd ★★★★ ()
Ответ на: комментарий от redixin

Раньше создавал ClientSession на каждую пачку, теперь создаю один в самом начале, не знаю, как правильнее будет.

panter_dsd ★★★★ ()

netstat показывает, что при нагрузке много соединений висят в TIME_WAIT, что есть странно - ClientSession должен ведь держать соединения открытыми, не?

panter_dsd ★★★★ ()
Ответ на: комментарий от panter_dsd

Завезли, но профайлер показывает на просадку во внутрянке пайтона

ОМФГ, даже профайлер не могут нормальный сделать.

no-such-file ★★★★★ ()

Отжешьбякакакая. Сегодня с утра копался, много всего перепробовал, полазал по нутрянкам и таки нашел ответ:

self.__session = ClientSession(connector=TCPConnector(limit=max_connections))

По-умолчанию, к одному эндпойнту создается максимум 10 подключений. Выставил сколько мне нужно и все взлетело.

panter_dsd ★★★★ ()
Ответ на: комментарий от NetSurf

Результаты стали достаточными для решения поставленной задачи. :)

panter_dsd ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.