Pull to refresh

Comments 25

За абстрактный пример — 5 (как мера абстрактности), за содержание — 2.
Если вы сами работали с этой библиотекой, можете сделать другой абстрактный пример, например, как будет выглядеть код для Ардуины Уно и любым wifi модулем на ваш вкус, в режиме сервера, чтобы контроллер получил запрос GET, отпарсил его, нашел запрашиваемый ресурс на SD-карте и отдал клиенту.
Дополнительно сразу хотелось бы уточнить, как будет реализовываться многопоточность (на выбраном wifi модуле), потому как фавиконку клиент запросит сразу же, до окончания передачи тела index.htm.
По поводу ардуины ничего не могу сказать, к сожалению — никакого опыта с ней нет :(
Ок, может кто из сообщества поделится опытом?
Ниже дал ссылку на подобный Ардуино-форк Монгуза, но старый и на питоне…
Кто-нибудь пытался реализовать подобное?
ArduinoMegaServer не предлагать, там свои тараканы и никак не ребята не отвяжутся от конкретных wifi чипов.
Я поясню, на всякий случай, вопрос.
Вот здесь представлен один дипломный проект, где разработчику удалось уместить всё в 2КБ оперативки Ардуины Уно. Но тут накручен питон и… и не раскрутить.
https://github.com/hdlj/Mongoose

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


Вроде как для тех, кого это не устраивает, есть civetweb, который является форком Mongoose от 2013-го года (когда Mongoose сменил лицензию).

Но меня вот какой вопрос интересует: если при обработке события MG_EV_HTTP_REQUEST не выставить флаг MG_F_SEND_AND_CLOSE, а передать запрос на обработку куда-то еще, то как отдать результат обработки в соединение когда этот результат будет таки получен (например, спустя 10 секунд после вызова обработчика)?
Нужно сохранить conn, и туда выдать ответ, когда он будет готов.
Я для этого делал очереди запросов. Также нужно мониторить соединения, чтобы если оно закрылось — отбраковать все запросы из очереди, которые связаны с данным соединением.
Это нужно делать на той же самой нити, где дергаются обработчики? Или можно с другой?
Я полагаю, что на той же.
Работать с одним соединением в разных потоках — плохая идея.
Тут весь плюс именно в асинхронной работе в один поток. Т.е. все что делает основной поток — это сетевой ввод-вывод, без диска, без сложной обработки.
Так запрос к базе у вас ведь идет в другом потоке?
поправьте плиз свой пример — чтобы было понятно когда нужно отдать ответ в сохраненный conn

Тогда нужно добавить очередь запросов и мониторинг соединений. Это значительно увеличит код.
Хорошо, чуть позже добавлю.
Запрос к базе может идти в том же потоке, если API базы позволяет. Если не позволяет — да, делаем отдельный поток и городим огород с синхронизацией. Но тогда это значительно нивелирует преимущества данного подхода.
Это не пугает — синхронизация не проблема. у меня и так там много ниток для других целей.
подскажите в какой момент вчитывается очередь ответов и в каком обработчике MG_EV_* нужно слать сообщение клиенту — это ведь нужно делать в нитке мангуста, а не в дочерней?
Я в комменте ниже описал.
А слать данные можно непосредственно когда их обнаружили в очереди, вне обработчика. Главное в том же потоке мангуста.
Ну так как раз в этом и вопрос: как из другого рабочего потока сказать Mongoose, что у меня есть данные на отправку, чтобы на своем потоке Mongoose дернул нужный коллбэк с нужным событием?
Тут без коллбэка. Вы просто в потоке мангуста помимо mg_mgr_poll() делаете еще поиск в очереди. Но тогда возникает проблема — mg_mgr_poll() придется делать с нулевым или очень маленьким таймаутом, т.е. чтобы не ждал новых событий. И тогда вы будете выжирать много CPU. Это и есть последствия того, что совмещаем два разных подхода — многопоточность и асинхронность. Возможно можно как-то обойти, но сейчас в голову пока ничего не идет.
Очевидно, что делать эти трюки внутри цикла вызовов mg_mgr_poll() — это ерунда. Интересует есть ли возможность зашедулить Mongoose какое-то пользовательское событие из другой рабочей нити. Чтобы Mongoose сам внутри mg_mgr_poll дернул callback с нужным флагом.
Ну первое что приходит на ум — слать ему какой-нибудь пакет TCP или UDP из потока с базой. Ну или HTTP-запрос, но это дороговато мне кажется.
Пользуюсь с 2014 года — все хорошо.
Сервер принимает запросы от десктопных клиентов в виде сжатого json по http
после обращения к БД возвращает результат так-же в виде json.

Под мангустом лежит sqlite база размером 17 гиг + levelDB 5 гиг

Можно подробнее про асинхронный запрос к БД
как вы его реализовали и в какой момент возвращаете результат?

у меня к бд коннект один но зовется она синхронно и
это оказывается узким местом в результате чего эта связка сносно работает только на VPS с SSD дисками.

Нагрузка у меня очень мелкая 10-20 запросов в секунду.
в каждом запросе пачки по 5-20 ключей размером 39 байт

т.е. в секунду идет 50-400 запросов
Насчет sqlite не подскажу, для PostgreSQL libpq позволяет делать асинхронные запросы.
Любое соединение с БД — это тоже сокет так или иначе. Так что если API СУБД позволяет асинхрон — вы в дамках :)
Спасибо за отзыв, интересно!
У sqlite нет сокета она так-же как и мангуст встраиваемая и состоит из одного файла на С
но я могу шарить соединение и делать запросы к базе в дочерних нитках.
как сделать очередь запросов представляю — пока не понял в какой момент отдавать назад результат клиенту.

Тогда самое простое — сделать два потока — один под мангуст, другой под работу с базой.
Сделать очередь запросов расшареной (привет блокировки!).
Поток мангуста:
1. Поступил HTTP-запрос — записали в очередь
2. Ищем в очереди запросы, для которых имеются готовые к выдаче ответы от БД и выдаем их клиентам
поток базы:
1. Ищем в очереди еще необработанные запросы
2. Нашли — запрашиваем у базы, получаем от нее ответ, если нужно обрабатываем (обработку вообще можно отдельным потоком сделать), записываем ответ в тот же элемент очереди.
Это если по-простому с блокировками очереди. Сюда можно присобачить семафоры/мьютексы чтобы не было напрасных sleep-ов.
идут протоптанной дорожкой — Apache/nginx +… А дальше начинается ад, потому что:...

Все-таки, отдельный HTTPD (чаще, конечно, nginx) — это не ад, а скорее удобство, поскольку вам не нужно заморачиваться с обработкой статических ресурсов, security, рутингом между несколькими инстацами, load balancing, всякой тонкой настройкой соединения и т.д. и т.п.


Так что если PHP в качестве backend не устраивает, то лучше (imho) сделать nginx + [ваш любимый C/C++ backend с HTTP (с тем же Mongoose) или *cgi].

Согласен, я даже про nginx написал пример конфига :)

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

Все супер конечно, но в 2016 вручную разбирать и собирать HTTP запросы как-то влом конечно добавляет гибкости, но и багов тоже.
Тут такой пиар создателя этой системки на «РБК вдруг появился. Решил посмотреть что это такое. Ну и, простите, чем это отличается от связки, например, FreeRTOS + UIP? Те же яйца, по-моему, только за лицензию никому и ничего платить не надо.
Sign up to leave a comment.

Articles