1

Имеется URL (http://site.ru/script.php), который нужно многопоточно запросить много раз подряд.

Я делаю так: создаю файл urls со 100500 одинаковыми урл-ами:

http://site.ru/script.php
http://site.ru/script.php
..
http://site.ru/script.php

И с помощью xargs и wget в даном случае в 10 потоков делаю так:

cat urls | xargs -t -P 10 -n1 wget --quiet -O -

Ну это ж как-то неправильно создавать по 100500 одинаковых урл-ов. Как по-другому можно подавать параметром на xargs тот же самый урл? Уточню, что необходим xargs, так как только он обеспечит многопоточность. Я думаю способ точно есть.

П.С.Тему назвал по-дурацки (но ничего другого не смог придумать), возможно модераторы поправят, если нужно.

2

Для этого есть siege

3 (21.02.2013 06:54:54 отредактировано valet)

neol пишет:

Для этого есть siege

Это совсем не тот инструмент, что мне нужен для данной задачи. siege предназначен для нагрузочного тестирования, то есть кроме просто отправки get-запросов он искусственно создает нагрузку, пересчитывает множество данных, что дает неплохой LA только от его работы.
У меня не стоит задача нагружать собственный сервер да еще и умышленно ab. Моя задача: многопоточно запрашивать скрипт по http для его выполнения.

4

как-то так можно, если на bash'е и в лоб...

for((i=0;i<100500;i++)) do echo http://site.ru/script.php]; done | xargs -t -P 10 -n1 wget --quiet -O -
95% процентов проблем находятся между клавиатурой и стулом.

5 (21.02.2013 07:37:39 отредактировано valet)

Fat-Zer пишет:

for((i=0;i<100500;i++))

не проверял, но вроде ж как очевидно что не годится, оно сожрет процессор, не разве.

6

Fat-Zer пишет:

и в лоб

это действительно слишком в лоб ))

Вот сейчас по мои идиотским запросам (не знаю как правильно сформулировать) нагугливается watch - вот никак не могу понять как его туда привязать и оно ли это вообще...

7

valet пишет:

не проверял но вроде ж как очевидно что не годится, оно сожрет процессор, не разве.

разве что 386-й...

valet пишет:

это действительно слишком в лоб ))

как ни крути получше, чем трюк с файлом...

valet пишет:

Вот сейчас по мои идиотским запросам (не знаю как правильно сформулировать) нагугливается watch - вот никак не могу понять как его туда привязать и оно ли это вообще...

нет... это чтобы выводить результат определённой команды через определённый период... как костыль конечно, наверное, можно прикрутить... но это ещё кривее...

95% процентов проблем находятся между клавиатурой и стулом.

8 (21.02.2013 08:01:10 отредактировано valet)

Fat-Zer пишет:

разве что 386-й...

Не соглашусь, в одном терминале запустил:

valet@valet-comp:~$ for((i=0;i<100500;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done & for((i=0;i<10050000;i++)) do echo http://site.ru/script.php; done

во втором видим:
http://s020.radikal.ru/i704/1302/da/917836012db9.jpg
То есть прилично нагружает все 4 ядра. А если таких вот паралельных запусков тоже 100500. В случае cat'ов - пожалуйста - нагрузка 0.

Fat-Zer пишет:

как ни крути получше, чем трюк с файлом...

неправда, cat работает не нагружаю процессор совсем, держу 100500 таких cat'ов - нагрузка по LA 0.

9

Вот вариант с cat'ом специально проделал:

valet@valet-comp:~$ for((i=0;i<100500;i++)) do echo http://site.ru/script.php >> file; done
valet@valet-comp:~$ cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & cat file & 

http://i068.radikal.ru/1302/15/7eefef191f90.jpg

10

Обратите внимание в том числе сколько вызовов cat - процессор не реагирует почти никак - текущая нагрузка такая и держится и без cat от других процессов.

11

Fat-Zer пишет:

как костыль конечно

да чувствую здесь и нужен какой-то костыль ab

12

valet пишет:

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

Какой-то странное у вас представление о его работе, ну да ладно.

for i in {1..100500}; do echo "http://site.ru/script.php"; done | xargs -t -P 10 -n1 wget --quiet -O -

Пойдет?

13

Кстати, а если это не для нагрузочного тестирования, то зачем дергать один и тот же скрипт 100500 раз?

14 (21.02.2013 08:54:10 отредактировано valet)

neol пишет:

Какой-то странное у вас представление о его работе, ну да ладно.

neol пишет:

Какой-то странное у вас представление о его работе, ну да ладно.

Siege – это утилита для нагрузочного тестирования веб-серверов. Она была создана для того чтоб дать разработчикам возможность проверить ресурсоёмкость своего кода в условиях, максимально приближенных к реальным.
В выделенном я подразумеваю что это будут не просто get-запросы, иначе чем бы она отличалась от штатного wget?
С siege когда-то игрался как раз для нагрузочного тестирования. Так вот я помню что там сам запущенный siege солидно жрет ресурсов, уже не говоря о том что он дает нагрузку на сервер куда коннектится - собственно для этого же и сделан этот инструмент ab, а мне надо как раз как можно меньше нагрузки давать на свой же собственный сервер.

neol пишет:

Пойдет?

так ведь опять же цикл ab. Ну ребята, ну цикли - это пожирание проца, ну какие циклы ab

neol пишет:

Кстати, а если это не для нагрузочного тестирования, то зачем дергать один и тот же скрипт 100500 раз?

ну ведь очевидно же, чтобы он 100500 раз исполнился ab
Или вы мне просто не хотите верить, что это моя задача действительно не для нагрузочного тестирования ab.

15

valet пишет:

Не соглашусь, в одном терминале запустил:

у тебя терминал тормозит... направь вывод в /dev/null

time bash -c '(for((j=0;j<10;j++)); do for((i=0;i<100500;i++)) do echo http://site.ru/script.php; done & done; wait) >/dev/null'

real    0m1.923s
user    0m7.164s
sys     0m0.250s

конечно cat быстрее и меньше кушает, но как ни крути, узкое место всё равно в wget'е...
к тому же этот файл ещё надо создать...

valet пишет:

Вот вариант с cat'ом специально проделал:

а вот за такие выкрутасы надо бить по щам...

alexander@goblin ~ $ for((i=0;i<100500;i++)) do echo http://site.ru/script.php; done >test_file
alexander@goblin ~ $ bash -c '(cat test_file & cat test_file)' | grep -v '^http://site.ru/script.php$'
http://site.ru/script.phhttp://site.ru/script.php
http://sp
http://site.ruite.ru/script.php
http://site.ru/script.ph/script.php
httpp
http://site.ru/scr://site.ru/script.php
http://site.ipt.php
http://site.ru/sru/script.php
http://site.ru/scripcript.php
http:/t.php
ht/site.ru/script.php
http://site.tp://site.ru/script.php
http://sitru/script.php
http://site.ru/scripe.ru/script.php
http://site.ru/st.php
htcript.php
http://site.ru/script.phtp://site.ru/script.php
http://sitp
http://site.rue.ru/script.php
/script.php
http://site.ru/scriphttp://site.ru/script.php
http://st.php
htite.ru/script.php
http://site.ru/script.phtp://site.ru/script.php
http://site.ru/scrp
http://site.ruipt.php
/script.php
http://site.ru/script.http://site.ru/script.php
http://sphp
httpite.ru/script.php
http://site.ru/script.ph://site.ru/script.php
http://site.p
http:/ru/script.php
http://site.ru/scrip/site.ru/script.php
http://site.rut.php
ht/script.php
http://site.ru/script.tp://site.ru/script.php
http://sitphp
httpe.ru/script.php
://site.ru/script.php
http://site.ru/scriphttp://site.ru/script.php
http://site.ru/st.php
http://sitcript.php
http:/e.ru/script.php
/site.ru/script.php
http://site.ru/script.http://site.ru/script.php
http://site.ru/sphp
http://site.cript.php
http:/ru/script.php
ht/site.ru/script.php
http://site.ru/script.tp://site.ru/script.php
http://site.ru/scrphp
http://site.ipt.php
http://sru/script.php
htite.ru/script.php
http://site.ru/script.phtp://site.ru/script.php
http://site.ru/scrp
http://site.ruipt.php
http://site.ru/scrip/script.php
httpt.php
http://sit://site.ru/script.php
http://site.ru/scripe.ru/script.php
t.php
http://sithttp://site.ru/script.php
http://site.ru/se.ru/script.php
cript.php
http://site.ru/script.phhttp://site.ru/script.php
http://sp
http:/ite.ru/script.php
http://site.ru/s/site.ru/script.php
http://site.ru/script.cript.php
http:/php
http://site./site.ru/script.php
http://site.ru/script.ru/script.php
htphp
http://site.tp://site.ru/script.php
http://site.ru/scrru/script.php
htipt.php
http://stp://site.ru/script.php
http://site.ru/scrite.ru/script.php
ipt.php

за предыдущее в принципе тоже, но echo намного реже будет давать такие осечки...

valet пишет:

неправда, cat работает не нагружаю процессор совсем, держу 100500 таких cat'ов - нагрузка по LA 0.

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

95% процентов проблем находятся между клавиатурой и стулом.

16

valet пишет:

ну ведь очевидно же, чтобы он 100500 раз исполнился ab
Или вы мне просто не хотите верить, что это моя задача действительно не для нагрузочного тестирования ab.

Если она не для нагрузочного тестирования, то у меня есть подозрение, что решаете вы ее не верно.
Зачем привлекать bash, wget и веб сервер к выполнению одного и того же кода, если можно сделать цикл в самом коде с тем же самым результатом?

17 (21.02.2013 10:05:45 отредактировано valet)

Fat-Zer пишет:

у тебя терминал тормозит... направь вывод в /dev/null

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

Fat-Zer пишет:

узкое место всё равно в wget'е...

узкое в чем? Во времени выполнения - это да и понятно почему, но процессор это не нагружает. А вот цикл нагружает по понятным причинам, а мне желательно не нагружать.

Fat-Zer пишет:

к тому же этот файл ещё надо создать...

да, но только 1 раз ab А важно чтобы при онлайн работе не тормозило.

Fat-Zer пишет:

а вот за такие выкрутасы надо бить по щам...

ну я привел чисто для примера чтобы посомтреть какая от этого будет нагрузка. Хотя не знаю почему, но у меня подобной каши при выводе не наблюдалось (если я правильно понял к чему вы клоните).

neol пишет:

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

ну решаю как умею ab

neol пишет:

Зачем привлекать bash, wget и веб сервер

постараюсь объяснить на примере одного из моих скриптов. Например я написал простенький web-паук на php+curl, который собирает нужную мне статистику. Его функционал в двух словах примерно такой: взять с sqlite-базы ссылку, загрузить страницу, собрать с нее по нужному критерию исходящие ссылки с нее и положить в ту же sqlite-базу. То есть каждый запуск такого скрипта будет проделывать это постоянно увеличивая базу. Тут по понятным причинам не получится применить организовать какой-то цикл внутри скрипта - да и не надо этого.
По поводу почему это bash - ну хотя бы потому чтобы обеспечить постоянную работу этого скрипта - например я могу запустить его многопоточное выполнение прямо с сервера, который постоянно в онлайне - то есть запустил, а он себе собирает базу...
Ну и еще по поводу цикла внутри скрипта - ну никак даже если бы это было логично - для веб-скриптов существует понятие "время выполнения скрипта", он не может выполнятся вечно или очень долго - его как минимум отклонит вебсервер по таймауту.
Ну и по многопоточности все понятно - чем больше ха единицу времени дерну скрипт - тем больше результатов он найдет и запишет в базу.
Вот и получается что скрипт, лежащий на http://site.ru/script.php нужно дергать большое количество раз и желательно многопоточно.

18

Без цикла же не обойтись, если только 10500 потоков одновременно запустить...

Да, у меня Ubuntu.
Нет, не глючит.

19

-=Serj=- пишет:

Без цикла же не обойтись, если только 10500 потоков одновременно запустить...

ну как же - пример с cat'ом без цикла работает ab

20

valet пишет:

ну как же - пример с cat'ом без цикла работает

Ну, насколько я понимаю, цикл присутствует внутри xargs.

Да, у меня Ubuntu.
Нет, не глючит.

21

valet пишет:

постараюсь объяснить на примере одного из моих скриптов. Например я написал простенький web-паук на php, который собирает нужную мне статистику. Его функционал в двух словах примерно такой: взять с sqlite-базы ссылку, загрузить страницу, собрать с нее по нужному критерию исходящие ссылки с нее и положить в ту же sqlite-базу. То есть каждый запуск такого скрипта будет проделывать это постоянно увеличивая базу. Тут по понятным причинам не получится применить организовать какой-то цикл внутри скрипта - да и не надо этого.

Я не вижу тут неразрешимых проблем. Что вас смущает?

valet пишет:

Ну и еще по поводу цикла внутри скрипта - ну никак даже если бы это было логично - для веб-скриптов существует понятие "время выполнения скрипта", он не может выполнятся вечно или очень долго - его как минимум отклонит вебсервер по таймауту.

Внезапно скрипт можно вызывать из cli с set_time_limit(0). Без ограничений по времени выполнения, wget'а, баша и дерганий веб сервера. И он сможет дергать ссылки ничуть не хуже, чем под управлением веб сервера.

22 (21.02.2013 10:41:25 отредактировано valet)

-=Serj=- пишет:

Ну, насколько я понимаю, цикл присутствует внутри xargs.

Ну насколько я понимаю, не совсем так. насколько мне видется его работа - xargs принимает параметры и разделяет эти параметры (по описанным в параметрам xargs например n1 - брать и передавать по одному параметру из входного потока) для передачи в скрипт тоже параметрами.
То есть например

cat urls | xargs -t -P 3 -n1 wget --quiet -O -

эквивалентно примерно следующем группам команд, выполняющимся пока не кончатся входные параметры для xargs, то есть пока не закончится вывод cat:

wget --quiet -O - http://url1_iz_urls & wget --quiet -O - http://url2_iz_urls & wget --quiet -O - http://url3_iz_urls
&&
wget --quiet -O - http://url4_iz_urls & wget --quiet -O - http://url5_iz_urls & wget --quiet -O - http://url6_iz_urls
&&
...
wget --quiet -O - http://urln-2_iz_urls & wget --quiet -O - http://urln-1_iz_urls & wget --quiet -O - http://urln_iz_urls

Ну и на мое удивление все это работает без какой либо нагрузки на процессор - деталей как это все организовано я не знаю, но это факт. Хотя бы потому что десятки таких скриптов запускаются подобным образом и LA при это стремится к нулю.

23 (21.02.2013 10:44:50 отредактировано valet)

neol пишет:

Внезапно скрипт можно вызывать из cli с set_time_limit(0). Без ограничений по времени выполнения, wget'а, баша и дерганий веб сервера. И он сможет дергать ссылки ничуть не хуже, чем под управлением веб сервера.

Можно, пробовал, мне не нравится. Там какие-то другие проблемы начинаются, сейчас точно не вспомню, но точно помню, что рассматривал это, но что-то меня потом остановило так делать.
Да и зачем это? Что это даст? Архитектура постановки задачи мне кажется тут правильно выполнена, скрипт простейший - взять с базы что-то, обработать, положить...

Да и вообще - сам язык php не рассчитан на это, это язык для веба, в таком случае такого паука уже лучше было бы писать на C или скажем каком-то серверном языке типа Python, но я просто написал на чем смог. Да и вопрос даже не конкретно в этом скрипте, у меня десятки подобных скриптов и все запускаю вот таким вот костылем через cat и xargs, просто считаю как-то тупо создавать файл с 100500 одинаковыми урл-ами.

24

valet пишет:

Можно, пробовал, мне не нравится.

valet пишет:

Да и вопрос даже не конкретно в этом скрипте, у меня десятки подобных скриптов и все запускаю вот таким вот костылем через cat и xargs, просто считаю как-то тупо создавать файл с 100500 одинаковыми урл-ами.

Ну нравится делать через задницу, так не удивляйтесь, что плохо пахнет.

valet пишет:

Да и зачем это? Что это даст?

Это выгоднее по ресурсам. И вообще правильнее, чем городить костыли.

valet пишет:

Да и вообще - сам язык php не рассчитан на это, это язык для веба, в таком случае такого паука уже лучше было бы писать на C или скажем каком-то серверном языке типа Python, но я просто написал на чем смог

18,5 миллионов результатов по запросу "php daemons" как бы намекают, что всем пофиг на что он рассчитан.

25 (22.02.2013 05:00:13 отредактировано valet)

Спасибо всем за участие в теме, расскажу к чему пришел.

Использую этот вариант:

neol пишет:

for i in {1..100500}; do echo "http://site.ru/script.php"; done | xargs -t -P 10 -n1 wget --quiet -O -

Пришел к выводу, что это лучший выход в данной ситуации. Да, вывод cat с file легче для процессора чем цикл, но ведь тот же файл я таким же циклом и генерю ab, записываю в него 100500 одинаковых строк - так что цикл этот, как правильно заметил -=Serj=-, никуда и так не деть ab. Вот в моем прежнем варианте кроме плохого стиля, нагрузки на процессор во время цикла еще и в IO вливалось...

neol пишет:

Ну нравится делать через задницу

через задницу, это использовать php через cli (он для этого мягко говоря не совсем предназначен) и заодно появляется куча подводных камней - грубо говоря чтобы вызывать с консоли

php script.php

надо этот самый скрипт чуть менее чем полностью ab переписать, уже не говоря о дополнительных требованиях при использовании php через cli, почитайте с хабра про сабж, если интересно.
Собственно я вот сейчас вспомнил почему я в свое время отказался от такой затеи - грубо говоря полностью рабочий (если вызывать по-человечески - то есть по http-протоколу с задействованием веб-сервера) и оттестированный скрипт отказался правильно работать через cli, выдавая при это кучу ошибок и ворнингов да еще и почему-то намного медленее, если таковых запустить множество...

neol пишет:

Это выгоднее по ресурсам.

Это очень спорное утверждение. Могу сказать, что накладные ресурсы затрачиваемые вебсервером (я практикую всегда только nginx + php-fpm) ничтожно малы по сравнению с скриптами. Поэтому ничего страшного в вызове php-скриптов привычным методом я не вижу. И вот это уже не знаю почему, выполняются они быстрее чем через cli. Ну в конце-концов это работает и работает быстро - а как говорится, работает - не трогай ab

26

valet пишет:

грубо говоря чтобы вызывать с консоли

php script.php

надо этот самый скрипт чуть менее чем полностью ab переписать, уже не говоря о дополнительных требованиях при использовании php через cli, почитайте с хабра про сабж, если интересно.

Если код написан нормально, то ему пофиг откуда его вызвали. Кроме обработки сигналов и, возможно, аргументов ничего из перечисленного в статье не окажет сильного влияния на содержание скриптов.

valet пишет:

Собственно я вот сейчас вспомнил почему я в свое время отказался от такой затеи - грубо говоря полностью рабочий (если вызывать по-человечески - то есть по http-протоколу с задействованием веб-сервера) и оттестированный скрипт отказался правильно работать через cli, выдавая при это кучу ошибок и ворнингов да еще и почему-то намного медленее, если таковых запустить множество...

unit тесты для него вы точно не писали (:

valet пишет:

Это очень спорное утверждение. Могу сказать, что накладные ресурсы затрачиваемые вебсервером (я практикую всегда только nginx + php-fpm) ничтожно малы по сравнению с скриптами. Поэтому ничего страшного в вызове php-скриптов привычным методом я не вижу. И вот это уже не знаю почему, выполняются они быстрее чем через cli.

"Выгоднее по ресурсам" и "потребляет меньше памяти/процессора/iops/дискового пространства" - это не синонимы. Процесс, запущенный с низким приоритетом, не будет мешать обрабатывать запросы в моменты пиковой нагрузки даже если он требует больше ресурсов.

Сокеты веб сервера (или php-fpm) - это тоже ресурс, причем достаточно ценный. Конечно если ваш сервер обслуживает клиентов, а не предназначен только для внутренних целей. На более-менее нагруженных проектах занимать сокет на длительное время ради какого-нибудь парсера вообще безумно расточительно.

Скрипты из cli выполняются медленнее например из-за apc/eaccelerator/xcache/zend optimizer (нужное подчеркнуть).
В статье по вашей ссылке это написано, кстати говоря.

27 (22.02.2013 14:10:56 отредактировано valet)

neol пишет:

Если код написан нормально, то ему пофиг откуда его вызвали.

после чего сразу же противоречите себе же ab

neol пишет:

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

neol пишет:

unit тесты для него вы точно не писали (:

конечно нет, какие тесты, если я написал скрипт (ну да, как умею), протестил его, убедился в правильности, тут возникла идея запустить проямо из командной строки - запустил, вообще не заработало, пошел редактировать, поменял метод приема параметров и т.д. и т.п., заработало, но засыпало ворнингами, попробовал многопоточно - намного медленнее все это...

neol пишет:

Процесс, запущенный с низким приоритетом, не будет мешать обрабатывать запросы в моменты пиковой нагрузки даже если он требует больше ресурсов.

мне как раз и не надо уменьшать приоритет - скрипты на рассматриваемом сервере - это основная его работа.

neol пишет:

Сокеты веб сервера (или php-fpm) - это тоже ресурс, причем достаточно ценный. Конечно если ваш сервер обслуживает клиентов, а не предназначен только для внутренних целей. На более-менее нагруженных проектах занимать сокет на длительное время ради какого-нибудь парсера вообще безумно расточительно.

возможно вы не знаете, для этого существует механизм пулов, которые в находятся в /etc/php5/fpm/pool.d/. Настраиваем пул forscripts.conf с нужными параметрами - с большим количество чилдренов и запросов на чилдрен и т.д. под скрипты и другой пул forsites.conf - под сайты, там уже чилдренов пару штук хватит. Пулы никак друг на друга не влияют, абсолютно независимы и даже если скриптовый пул перегружен или даже перестанет отвечать от нагрузки и скрипты перестанут обрабатываться, то пул для сайтов при этом продолжит работать. На одном из серверов у меня так и организовано - полет нормальный.
Но повторюсь, рассматриваемый сервер исключительно для работы и тестирования скриптов. Собственно я и хочу использовать все его ресурсы именно для этого.

neol пишет:

Скрипты из cli выполняются медленнее например из-за apc/eaccelerator/xcache/zend optimizer (нужное подчеркнуть).

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