LINUX.ORG.RU

Микросервисный движок мегатрон

 


0

2

Привет, запилил фрейморк под сервисную модель программирования или акторную, кому как нравится. По скорости демки хттп сервера уделывает nginx примерно на 2%. Билдится под линуксом и макосью.

Очень удобно реализована возможность создания консоли для сервера на телнете. Eсть возможность создавать иерархическое облако. Сорцы тут:

https://github.com/akakist/megatron

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

Это курьез с одной работы. Кстати погугли вопрос как делать таймер на C++ Таймер реально так и сделали. Без нагрузки пойдет, а потом останутся мелкие ошибки, которые несложно поправить года за 3.

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

Кстати, 300к rps - это виртуалка убунты на vmware под маком м1. У меня многопоточный еполл. Почему на виртуалке такая высокая скорость - сам не понимаю, обалдел, как увидел.

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

Это курьез с одной работы. Кстати погугли вопрос как делать таймер на C++ Таймер реально так и сделали. Без нагрузки пойдет, а потом останутся мелкие ошибки, которые несложно поправить года за 3

даже и не спорю, джаст фор фан бывает,тут есть перц с проектом - там 1 таймер = 1 тред.

просто just-for-fun, и так делать это очень сильно разное.

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

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

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

Там вообще жестокий идиотизм с этим таймером. Detached state если сам таймер прибился по выходу из стека, либо его вязать куда-то unique_ptrом. Плохо помню, там недолго терпения хватило. Но как сделать то таймер без фреймворка - нигде информации нет. Получается, что у каждой компании должен быть фреймворк. Без него даже начинать проект - такое себе.

akakist
() автор топика
Ответ на: комментарий от alysnix

Обычно таймер кажется простым обьектом, на который можно дать час рабочего времени. А у тебя специальный тред, пул воркеров и тп. Тем более, что тривиальный таймер с новым потоком гуглится.

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

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

вся система таймеров пишется за час-два на с++. нужны только треды, мьютексы, и cond var. по простому - делают отдельный тред таймеров, который и запускает те таймеры, что в очереди, как только придет из время.

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

примерно такие таймеры есть во всяком уважающем себя плюсовом фреймворке. если таймеров нет - значит фреймворк куцый и не имеет даже базовой функциональности.

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

а релаьные таймеры более строго привязаны ко времени, чем твой вариант с ивентами

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от alysnix

Так - ты делаешь отдельный поток таймера. Затем пихаешь в него лямбду по сути. Когда приходит время тред таймера выполняет лямбду, верно? В этом случае у тебя появляется многопоточность и все члены класса, который вызвал таймер, нужно лочить мутексами или атомиками. Я делал тест с атомиком. Инкремент под атомиком и под мутексом. Атомик оказался в 2 раза быстрее. Т.е. 2 инкремента атомика уже равны по стоимости одному мутекслоку. В итоге приходим к тормозной программе, которая по скорости хуже гоу.

akakist
() автор топика
Ответ на: комментарий от alysnix

Таймер у меня заточен на периодичность для протокола. Т.е. когда среагировать на PONG_TIMEDOUT, например. Там точность не нужна особо. Eстественно есть время для прохождения евента от консьюмера к таймеру. В евент таймера я помещаю сокаддр хоста, куда долбился и могу еще дополнительные данные указать, которые не влияют на идентификацию таймера. Когда прилетел timerAlert, я вытаскиваю данные и вижу какой сокаддр и могу заного начать диаграмму активности maintaining connection именно с этим хостом. Мне не нужно хранить какие-то мапы для данных, связанных с евентом таймера. Довольно удобно сделано.

akakist
() автор топика
Ответ на: комментарий от alysnix

вся система таймеров пишется за час-два на с++. нужны только треды, мьютексы, и cond var. по простому - делают отдельный тред таймеров, который и запускает те таймеры, что в очереди, как только придет из время.

задача выставила таймер - что-то там в расширенных очередях улетело в соседний тред. Потом таймер тикнул, пошла работать лямбда, но начальная задача её вытеснила ибо не@#уй :-)

как-то так работают таймеры через треды :-)

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

Грубо так выглядит алгоритм поддержки соединения Аларм - единичный сигнал

PING { setAlarm(sockaddr) PONG_TIMEDOUT, setAlarm(sockaddr) PING_RESEND_TIMEOUT }

<PONG { resetAlarm(sockaddr) PONGTIMED_OUT, PING, setAlarm(sockaddr) PING_RESEND_TIMEOUT } <PONG_TIMEDOUT - connection lost.

Как-то так. Просто берем диаграмму активности и раскидываем на евенты. Тупее методики программирования не существует. Высокая скорость и минимум ошибок.

akakist
() автор топика
Ответ на: комментарий от alysnix

если вам надо чтобы код таймера имел приоритет над пользовательскими тредами - повысьте приоритет треда таймеров. можете сделать разноприоритетные таймеры.

задачи которые выставляют таймеры приоритетны by-design. Иначе бы обходились чтением меток времени.

я понимаю, через соседний свободный тред оно формулируется всё очень просто. И реализация не сложна. Но есть проблема.. Ядро уже упоролось чтобы довести вызов таймера, так оказывается его обманули - и вызов не туда :-)

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

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

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

akakist
() автор топика
Ответ на: комментарий от MKuznetsov

Через соседний поток она как раз решается чрезвычайно сложно, за это придется заплатить упарыванием на отладке внезапно возникшей многопоточности.

Решается такая задача только приведением класса в вид сервиса, т.е. у него есть евентлуп с одним мутексом. Только одним, который отладить легко. Таймер пихнул свой алерт в очередь сервиса, потом евентлуп выдернул евент таймера и исполнил в потоке сервиса. То есть в одном потоке. Весь код сервиса выполняется в одном потоке и не требует упарывания по теме многопоточности.

akakist
() автор топика
Ответ на: комментарий от MKuznetsov

задачи которые выставляют таймеры приоритетны by-design. Иначе бы обходились чтением меток времени.

не надо читать никакие «метки». в event-driven все управляется ивентами.

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

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

alysnix ★★★
()

Можете заценить как все с сокетами сделано. Один сервис, который мультиплексирует сокеты, читает буфера тоже. События с прочитанными данными и всякие connection_losts посылает консьюмерам, которые заказали слушать сокет. А они уже потом сами разгребают поток данных. Т.е. все протоколы - хттп, рпц телнет висят на одном мультиплексоре

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

Зацените еще телнет. Сорцы гляньте. Один евент зарегистрировать команду и потом прилетает евент, что команда введена и буфер, что введено, даже регексповый фильтр параметров команды сделан. При этом список команд телнета динамический, зависит от запущенных сервисов.

Обычно я делаю сервисы плагинами, сделайте make install

Они запускаются не все, а только те, кто указан в конфиге и к кому прилетел евент.

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

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

Мысля - у дрогона все сделало на врапперах позикса из STL, а и у меня - все самописные. При прочих равных у меня скорость в 4 раза выше. Может из-за этого?

akakist
() автор топика

cmake - просто кровь нафиг из глаз

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC ")

все вручную установленные CMAKE_C{XX}_FLAGS - на мороз.

target_compile_features(${TARGET} PUBLIC cxx_std_17)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)

вернуть find_package(OpenSSL) и компилять с -DOPENSSL_ROOT_DIR=/path/to/openssl. Зависимость от 1.1.1 - на мороз, эта версия давно устарела.

Про то, что там творится в подпроектах, я вообще молчу.

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

За cmakelists.txt - очень извиняюсь, сам понимаю, что дно. Попробую поправить. OpenSSL 1.1.1 - оптимум, там потом использованные функции депрекейтнулись. Надо переделывать на новый апи. Но по хорошему там ССЛ нужен для OscarSecure. Eсли его делать корректно, то там нужно сертификаты добавлять и нормально обрабатывать. Опять же как в облаке на все ноды нагенерить сертификатов, я хз. Плюс для OscarSecure нужна мапа для сессий и локи. Там, если можно заметить, используется ListenerSimple. Это листенер, который сразу вызывает handleEvent без буферизации. Буферизация дает очень существенные тормоза. Для телнета катит, а для рпц, оскара - нет. Слово оскар сперто с протокола AIM, но там остались от него рожки да ножки. Кстати, интересно прикинуть, что происходит со стеком, когда ListenerSimple включен. Особенно если обратные евенты посылаются. Что-то подобное языку форт, возможно. Т.е. с ним нужно очень аккуратно.

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

потому что безусловное включение в системе сборки логики больше строго необходимой - это путь к багам и проблемам с интеграцией. А для тех кто опакечивает софт в дистрах онтопика - вообще головная боль.

Особенно не надо писать if (CMAKE_BUILD_TYPE == Debug) ... и т.п., это не совместимо с ninja multi-config.

Lrrr ★★★★★
()

Охохо господуля, добро пожаловать в клуб писателей веба на С++

Мы вот делаем https://nanochat.ru/main на примерно такой же штуке, но самописной. У нас раньше на Makefile всё было, а потом придумали свой недо-DSL в 100 раз проще чем CMake а на нём херачим.

lesopilorama
()
Последнее исправление: lesopilorama (всего исправлений: 1)

Рекомендую выписать в список части твоей системы, и посмотреть как эти вещи сделаны в других популярных, хорошо написанных проектах. Некоторые решения показались очень плохи. Много где нету обработки ошибок. И я не распознал диалект венгерской нотации, не похоже на Win/C++, если это должна быть она, то стоит перечитать еще раз правила именования.

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

Мы тоже писали уеб чат в свое время. Там тоже своя система сборки была, cmake удобнее, но лучше на нем не делать кучу зависимостей find_package. Например, усервер сбилдить - это подвиг. Я его обрезал по максимуму, чтобы затестить и сравнить с мегатроном. Результат: в 17 раз медленнее.

akakist
() автор топика
Ответ на: комментарий от MOPKOBKA

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

akakist
() автор топика