BG Development


Страници: (5) [1] 2 3 ... последна »  ( Първото ново мнение ) Reply to this topicStart new topicStart Poll

> (Бърз)? framework за сървъри на PHP
raxbg
Публикувано на: 18-03-2018, 12:29
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 356
Регистриран на: 16.03.12



Здравейте, работя върху фреймъурк за писане на сървъри на PHP (например WebSocket, HTTP). Основния цикъл за сървърите май е стабилен вече, и работя предимно по вградените wrapper-и за HTTP и WebSocket. За момента производителността е доста добре - WebSocket е като в NodeJS, а HTTP е по-бързо от Node-а.

Тествах и спрямо Ratchet, AmPHP и ReactPHP, но при тях пърформънса е доста зле и не знам дали просто тестовите приложения, които съм написал не са както трябва. Та може ли който е запознат с някой от тези проекти да сподели код за тестване? Тестовете трябва да са аналогични на тези описани тук https://psockets.com/performance.

П.С. Моето проектче се казва Psockets. Ако някой се интересува може да разгледа това което съм качил на https://psockets.com до момента или да разгледа репото в GitHub. Приемам и предложения за нови функционалности или за по-добра структура на цялото нещо icon_lol.gif

П.С.2 Сайта си се хоства от този фреймуърк без допълнителни сървъри като Apache или NGINX icon_razz.gif


--------------------
“ Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ”
Brian Kernighan
PMEmail Poster
Top
gat3way
Публикувано на: 18-03-2018, 14:51
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 2318
Регистриран на: 22.06.12



Значи доколкото се ориентирам набързо, за всеки сървър имаш списък с файлови дескриптори върху които викаш select и въртиш един безкраен цикъл със select върху fd set-овете от всеки сървър. Това няма да скалира добре - с http може би няма да го разбереш толкова скоро, но с websocket-ите със сигурност ще забележиш драмата.

Първият проблем е че имаш няколко fd set-а, за всеки сървър по един. Безсмислено е това, защо просто не ги навреш всичките в един и не викаш само веднъж select-а и като има събитие да го обслужваш в зависимост от сървъра за който са, това ще подобри малко латентността. То select-а си се вика без timeout де, което в случая не изкарва на повърхността този проблем достатъчно добре, въпреки че от друга страна това не е добра идея според мен. Каква е CPU утилизацията като пуснеш сървъра?

А другият вариант е всеки сървър да си е със собствен fd set, но в отделна нишка, всъщност това е добра идеа за утилизиране на ресурсите на многоядрена машина (защото с твоя дизайн в момента не се възползваш от това). Макар че и това не е оптимално.

И накрая, select е лоша идея сам по себе си. Аз одеве споменах че няма да го усетиш лесно с http, но с websocket-ите като нищо ще се нахендриш, това е защото http връзките са краткотрайни (дори с keep-alive, което не погледнах дали го handle-ваш, но би трябвало - за https връзки особено е много добра идея). А е лоша идея първо защото скалира много зле с броя на fd-тата в set-а. И второ е лоша идея защото select-а подържа максимум 1024 файлови дескриптори. Това не е защото ти нещо лошо правиш, а защото е ограничение на системното извикване отдолу. В php-то няма ли poll(), там няма ограничения откъм максимален брой дескриптори, а и се държи малко по-добре.
PMEmail Poster
Top
raxbg
Публикувано на: 18-03-2018, 16:19
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 356
Регистриран на: 16.03.12



QUOTE
Първият проблем е че имаш няколко fd set-а, за всеки сървър по един. Безсмислено е това, защо просто не ги навреш всичките в един и не викаш само веднъж select-а и като има събитие да го обслужваш в зависимост от сървъра за който са, това ще подобри малко латентността.


Първоначално така беше, но кода почна да се омазва доста. Сега като съм го пооправил малко мога да направя втори опит.

QUOTE
То select-а си се вика без timeout де, което в случая не изкарва на повърхността този проблем достатъчно добре, въпреки че от друга страна това не е добра идея според мен.


Защо?

QUOTE
Каква е CPU утилизацията като пуснеш сървъра?


Зависи. Idle в момента ми е ~2%, но това лесно се променя от един usleep в ServerManager цикъла. Когато се натовари и до 100% може да стигне, ама това е нормално мисля. То зависи какво прави сървъра и колко са връзките които обслужва.

QUOTE
А другият вариант е всеки сървър да си е със собствен fd set, но в отделна нишка, всъщност това е добра идеа за утилизиране на ресурсите на многоядрена машина (защото с твоя дизайн в момента не се възползваш от това). Макар че и това не е оптимално.


Така е, но това изисква pthreads екстеншъна. Като цяло ако искаш няколко такива сървъра да ти рънват на различни ядра, може просто да пуснеш всеки в отделен процес и да закачиш процесите на отделни ядра.

QUOTE
И накрая, select е лоша идея сам по себе си. Аз одеве споменах че няма да го усетиш лесно с http, но с websocket-ите като нищо ще се нахендриш, това е защото http връзките са краткотрайни (дори с keep-alive, което не погледнах дали го handle-ваш, но би трябвало - за https връзки особено е много добра идея). А е лоша идея първо защото скалира много зле с броя на fd-тата в set-а. И второ е лоша идея защото select-а подържа максимум 1024 файлови дескриптори. Това не е защото ти нещо лошо правиш, а защото е ограничение на системното извикване отдолу. В php-то няма ли poll(), там няма ограничения откъм максимален брой дескриптори, а и се държи малко по-добре.


Да keep-alive се поддържа, че иначе SSL negotiation на всеки рикуест е доста грубо. Относто лимита от 1024 fd-та на селект, не може ли да се заобиколи като си сплитна целия сет на събсетове от по 1024? Не знам да има poll() в PHP.


--------------------
“ Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ”
Brian Kernighan
PMEmail Poster
Top
lucky
Публикувано на: 18-03-2018, 16:39
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 410
Регистриран на: 05.08.17



има libevent в php, та това определено е вариант, особено за websockets според мен

за timeout-a, има инфо в документацията на stream_select.

При всички положения интересн проект, браво icon_cool.gif
PMEmail Poster
Top
raxbg
Публикувано на: 18-03-2018, 16:55
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 356
Регистриран на: 16.03.12



Libevent е в TODO листа icon_razz.gif


--------------------
“ Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ”
Brian Kernighan
PMEmail Poster
Top
gat3way
Публикувано на: 18-03-2018, 17:25
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 2318
Регистриран на: 22.06.12



QUOTE
QUOTE
То select-а си се вика без timeout де, което в случая не изкарва на повърхността този проблем достатъчно добре, въпреки че от друга страна това не е добра идея според мен.


Защо?


Защото е busy wait и гориш процесорно време напразно. Конкретно за твоят сървър това не е проблем, но става проблем за останалите процеси на системата. Но тъй като нещата са навързани (например обработването на заявката може да включва комуникация с някаква база която върви на същия хост), то не е проблем да си правиш сечено в крайна сметка.

usleep-а разбира се решава нещата с утилизацията....привидно поне. Лошото е че за времето за което "спиш" не обслужваш никакви събития по сокетите, което ти вдига латентността на заявките. Таймаута решава тези неща - select-а блокира докато не се случи събитие или не изтече таймаута. В случая в който обаче имаш няколко fd set-а и поредни викания на select(), това става проблем. Примерно имаш три set-а, таймаут от секунда, в първите два нямаш събития, в третия имаш събитие. Последното ще се обслужи най-рано след 2 секунди, което е лоша работа.


QUOTE
Така е, но това изисква pthreads екстеншъна. Като цяло ако искаш няколко такива сървъра да ти рънват на различни ядра, може просто да пуснеш всеки в отделен процес и да закачиш процесите на отделни ядра.


Напълно валиден подход. Е няма как да слушат на един и същ порт което е лошото, ще трябва някое reverse proxy да разхвърля и балансира заявките по сървърите.


QUOTE
Относто лимита от 1024 fd-та на селект, не може ли да се заобиколи като си сплитна целия сет на събсетове от по 1024? Не знам да има poll() в PHP.


А, произволен брой списъци с дескриптори можеш да имаш на които да викаш select, проблемът е че както казах, не им понася по-голяма бройка (и не подържат над 1024). Та това дето го мислиш ще изисква също и някаква логика за да разпределяш новите връзки по set-овете, абе значително по-просто е ако ползваш нещо по-читаво от select, не мога да повярвам че няма poll в пхп-то.

Това мнение е било редактирано от gat3way на 18-03-2018, 17:26
PMEmail Poster
Top
raxbg
Публикувано на: 18-03-2018, 18:06
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 356
Регистриран на: 16.03.12



QUOTE
QUOTE
QUOTE
То select-а си се вика без timeout де, което в случая не изкарва на повърхността този проблем достатъчно добре, въпреки че от друга страна това не е добра идея според мен.


Защо?


Защото е busy wait и гориш процесорно време напразно. Конкретно за твоят сървър това не е проблем, но става проблем за останалите процеси на системата. Но тъй като нещата са навързани (например обработването на заявката може да включва комуникация с някаква база която върви на същия хост), то не е проблем да си правиш сечено в крайна сметка.


Благодаря, ще видя какво мога да направя по въпроса.

QUOTE
usleep-а разбира се решава нещата с утилизацията....привидно поне. Лошото е че за времето за което "спиш" не обслужваш никакви събития по сокетите, което ти вдига латентността на заявките. Таймаута решава тези неща - select-а блокира докато не се случи събитие или не изтече таймаута. В случая в който обаче имаш няколко fd set-а и поредни викания на select(), това става проблем. Примерно имаш три set-а, таймаут от секунда, в първите два нямаш събития, в третия имаш събитие. Последното ще се обслужи най-рано след 2 секунди, което е лоша работа.


Не е точно така, защото usleep-a се вика само ако при последните 3 завъртания на цикъла не е имало нищо за правене. Тогава сървъра си позволява да заспи. Идеята е, че така може да има малко забавяне ако не се е случвало нищо за известно време, но ако има работа се цикли без прекъсване.

QUOTE
QUOTE
Така е, но това изисква pthreads екстеншъна. Като цяло ако искаш няколко такива сървъра да ти рънват на различни ядра, може просто да пуснеш всеки в отделен процес и да закачиш процесите на отделни ядра.


Напълно валиден подход. Е няма как да слушат на един и същ порт което е лошото, ще трябва някое reverse proxy да разхвърля и балансира заявките по сървърите.


Ми то и сега не може на 1 порт да имаш повече от един сървър icon_lol.gif. За момента на 1 порт може да има само 1 сървър и 1 протокол "wrapper". Имах идея да направя така че да имаш повече от 1 wrapper, за да може например HTTP wrapper-a да forward-ва към WebSocket когато трябва да се ъпгрейдва връзката, обаче сметнах, че има по-важни неща за оправяне от това. По някое време и това ще направя и тогава ще го има този проблем - да icon_lol.gif

QUOTE
QUOTE
Относто лимита от 1024 fd-та на селект, не може ли да се заобиколи като си сплитна целия сет на събсетове от по 1024? Не знам да има poll() в PHP.


А, произволен брой списъци с дескриптори можеш да имаш на които да викаш select, проблемът е че както казах, не им понася по-голяма бройка (и не подържат над 1024). Та това дето го мислиш ще изисква също и някаква логика за да разпределяш новите връзки по set-овете, абе значително по-просто е ако ползваш нещо по-читаво от select, не мога да повярвам че няма poll в пхп-то.


Much sadness icon_sad.gif


--------------------
“ Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ”
Brian Kernighan
PMEmail Poster
Top
gat3way
Публикувано на: 19-03-2018, 00:59
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 2318
Регистриран на: 22.06.12



QUOTE
Ми то и сега не може на 1 порт да имаш повече от един сървър icon_lol.gif. За момента на 1 порт може да има само 1 сървър и 1 протокол "wrapper". Имах идея да направя така че да имаш повече от 1 wrapper, за да може например HTTP wrapper-a да forward-ва към WebSocket когато трябва да се ъпгрейдва връзката, обаче сметнах, че има по-важни неща за оправяне от това. По някое време и това ще направя и тогава ще го има този проблем - да icon_lol.gif


Аз имах предвид по-различно нещо, паралелизъм не на ниво сървър, а на ниво fd set. Например ако няма наистина алтернатива на select(), можеш всеки fd set да си го select-ваш в отделна нишка, това няма да спести разбира се драмите с това да балансираш set-овете, но ще можеш спокойно да си позволиш таймаут на select-а и да разкараш спането. Като добавен бонус, така натурално ще утилизираш многоядрената система. Може и в отделни процеси, но според мен е по-сложно така (междупроцесното IPC е по-криво, а в случая с нишките единствено вероятно ще се разминеш с един мутекс който ще трябва да заключваш като модифицираш set-овете). А и е по-скапано решение от гледна точка на производителността, защото превключването между таскове с различни адресни пространства (различни процеси) е по-скъпо, отколкото между таскове с едно и също (нишки демек).

Всъщност, същият номер може да се направи дори да не ползваш select, ами poll или изгъзици като epoll, вече с идеята да утилизираш ядрата. Виждал съм такива изпълнения.


QUOTE
Така е, но това изисква pthreads екстеншъна. Като цяло ако искаш няколко такива сървъра да ти рънват на различни ядра, може просто да пуснеш всеки в отделен процес и да закачиш процесите на отделни ядра.


Това на второ четене като се замисля може би така или иначе ще ти се наложи, няма как да направиш всичко асинхронно със средствата на PHP. Например за да е всичко прекрасно и както трябва, ще трябва и SQL заявките да са асинхронни, аз отдавна не съм се интересувал от пхп, ама доколкото помня всичките варианти за mysql и psql API-та дето бяха там си бяха съвсем синхронни, което означава че ако ги ползваш, ще ти блокират event loop-а. Единият вариант е да си напишеш from scratch твоя си библиотека за това и тя да си вкарва сокетите които отваря до базата в event loop-а и всичко да е розово и прекрасно, но това означава сам на PHP да имплементираш цялата тази свинщина, което е бая къртовски труд. А другото е да емулираш асинхронността като вдигаш нишки дето вършат синхронната работа и да го накараш за пред хората това да изглежда асинхронно. Обаче и това може да се окаже забава, например най-първото което ще ти хрумне в главата е някъде в event loop-а да сложиш pthread_join или нещо от сорта, за да знаеш кога е свършило това и да викнеш колбека. Обаче хаха, в POSIX няма дефиниран неблокиращ pthread_join, в линуксчето има...ма си е нестандартно, няма как да го ползваш на друга платформа. Пък и дори не знам non-posix функциите в линуксчето дали са ги expose-нали в пхп-то.

Абе приключение си е това всичкото, някои хора усилено твърдят че вебаджийството е за идиоти, точно това обаче изобщо не е за идиоти, доста забавна главоблъсканица е.
PMEmail Poster
Top
AK-85
Публикувано на: 19-03-2018, 06:14
Quote Post



Име:
Група: Потребител
Ранг: Старо куче

Мнения: 739
Регистриран на: 06.07.06



QUOTE (gat3way @ 18-03-2018, 16:25)
Конкретно за твоят сървър това не е проблем, но става проблем за останалите процеси на системата.

Не точно, защото като процесът си изчерпа времевия квант, ядрото ще го приспи насила (освен ако някой не си е играл да го направи real time), т.е. за останалите поведението ще е еквивалентно на това при натоварен сървър.

QUOTE (gat3way @ 18-03-2018, 16:25)
Примерно имаш три set-а, таймаут от секунда, в първите два нямаш събития, в третия имаш събитие. Последното ще се обслужи най-рано след 2 секунди, което е лоша работа.

Това на PHP-то ли е някаква глупост?

QUOTE (gat3way @ 18-03-2018, 16:25)
Е няма как да слушат на един и същ порт което е лошото, ще трябва някое reverse proxy да разхвърля и балансира заявките по сървърите.

Като се отвори приказка за платформенозависими API-та, в PHP-то не е ли вкарана поддръжка на SO_REUSEPORT?

QUOTE (gat3way @ 18-03-2018, 23:59)
А другото е да емулираш асинхронността като вдигаш нишки дето вършат синхронната работа и да го накараш за пред хората това да изглежда асинхронно. Обаче и това може да се окаже забава, например най-първото което ще ти хрумне в главата е някъде в event loop-а да сложиш pthread_join или нещо от сорта, за да знаеш кога е свършило това и да викнеш колбека.

Винаги е вариант да ползваш detach-нати нишки и неблокиращ механизъм за нотификация.
PM
Top
gat3way
Публикувано на: 19-03-2018, 09:54
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 2318
Регистриран на: 22.06.12



QUOTE
Не точно, защото като процесът си изчерпа времевия квант, ядрото ще го приспи насила (освен ако някой не си е играл да го направи real time), т.е. за останалите поведението ще е еквивалентно на това при натоварен сървър.


Така е, света няма да свърши, но пак е напълно безсмислено.

QUOTE
Това на PHP-то ли е някаква глупост?


Мне, това е в неговия случай, той има един "голям цикъл" в който последователно вика select върху няколко set-а от дескриптори.

QUOTE
Като се отвори приказка за платформенозависими API-та, в PHP-то не е ли вкарана поддръжка на SO_REUSEPORT?


Знам ли?

QUOTE
Винаги е вариант да ползваш detach-нати нишки и неблокиращ механизъм за нотификация.


Мдам.
PMEmail Poster
Top
1 потребители преглеждат тази тема в момента (1 гости, 0 анонимни потребители)
Потребители, преглеждащи темата в момента:

Topic Options Страници: (5) [1] 2 3 ... последна » Reply to this topicStart new topicStart Poll

 


Copyright © 2003-2018 | BG Development | All Rights Reserved
RSS 2.0