Pull to refresh

Comments 24

мы в MariaDB сейчас доводим до ума (и уже почти довели) асинхронный API для libmysqlcient. Там как раз и используется makecontext/swapcontext (или ассемблерные вставки, или windows fibers — что где).

Это полностью в libmysqlclient, так что должно работать и c официальным mysqld.

вот дерево: code.launchpad.net/~maria-captains/maria/mariadb-5.2-mwl192

скоро будет и релиз.
Обалдеть! Пожалуй, есть смысл применять для кроссерверных взаимодействий между доверенными серверами (что-то вроде внутреннего URL-API), обычных-то юзеров по таким ссылкам лучше не пускать.
Сами локейшины с запросами могут быть закрыты для обычных юзеров (при помощи internal). Обращаться к ним проще всего через подзапросы или проксировать на них клиентские соединения с нужными проверенными аргументами.
А именованные локейшны можно использовать? (Те, которые с "@" начинаются)
Перехват/трассировка часто используемых функций типа read() может отрицательно повлиять на производительность. У нас, когда мы сокеты трассировали, overhead в некоторых сценариях доходил до десятков процентов (но мы еще время вызовов меряли, и фильтровали сокеты от файлов — это очень сказывалось).
Интересная система выходит NGINX который асинхронно обращается напрямую в MySQL.

А можете привести несколько примеров где есть смысл такое использовать?
Я сходу не могу придумать и наверное потому что не сталкивался с задачами с которыми вы встретились.
Например так:
Представьте, что у вашего проекта куча пользователей, которые «живут» на разных бекендах (оставим за скобками смысл самого проекта, пусть у них там хранилище какое-нибудь). Вопрос — как хранить соответствие «пользователь-бекенд»? Самое простое решение — использовать хеш от имени. Но иногда (довольно часто) это не подходит и нужно хранить индивидуальные соответствия. Вот при помощи такого модуля вы можете получать номер бекенда из базы данных и сразу же проксировать соединение на нужный бекенд.

Или представьте, что у вы хотите проксировать соединение на скрипт, у которого нет доступа к БД (или вы не хотите давать ему такой доступ, или это не ваш адрес и вы вообще ничего не можете кроме как проксировать туда). Вот берете и передаете ему в аргументах все, что нужно, предварительно получив это из бд.

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

Ну и самый общий случай — вообще логику многих веб-приложений можно частично реализовывать в NGINX, доступ к MySQL расширяет возможности таких «встроенных» приложений.
Теперь я понимаю для чего это. Действительно я с подобным не сталкивался, но это реальные проблемы которые можно легко решить.
Спасибо за подробные примеры!
Почему в таком варианте не использовать nosql?
Вообще NoSQL можно использовать много где. Но часто нужен именно нормальный MySQL — так просто удобнее.
а в чем удобство? Тут же просто фронтэнд стоит, который обращается к бекэндам. По-моему, действительно будет лучше использовать простенькую табличку id -> id бекэнда nosql.

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

Кстати видимо реально сделать тулзу для автоматического изготовления асинхронной версии произвольной библиотеки для NGINX по методу rarutyunyan (a-la SWIG).
Собственно, есть модуль nginx-mtask-module, который и делает ровно это в отрыве от конкретной библиотеки. Но, конечно, в каждом конкретном случае надо смотреть на библиотеку, что она там зовет.
В NGINX модули вроде бы линкуются статически; почему не происходит перехвата вызовов, которые делает сам NGINX?
Происходит. Но тогда, когда переключение контекста не нужно, вызовы проксируются дальше — в libc. Например, в перехваченном read происходит вызов настоящего read и в некоторых случаях мы сразу же возвращаем его результат, ничего не переключаем.
Как раз затем, чтобы не перекомпиливать. Кстати сам клиент libmysqlclient написан так, что если есть желание перекомпиливать, ему можно достаточно удобно «подсунуть» нужные реализации функций ввода-вывода, они там удобо собраны в одну структуру и зовутся всегда через нее. Но это уже совсем другая история.
Мне не совсем понятно, почему если не нужна перекомпиляция — это преимущество.

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

Перехват системных вызовов много где используется. Я например имел дело с fakeroot (перехват системных вызовов для симуляции суперпользователя, часто используется при сборке пакетов). Но там цена ошибки много ниже. Ну упадет процесс одной из запущенных утилит, сборка обломается.

А если упадет NGINX, это будет намного более заметно.
Лично я считаю, что если у вас в системе стоит одна актуальная версия libmysqlclient и вы ее (одну и ту же) везде используете, то это хорошо и удобно. Но вы можете считать иначе и перекомпиливать ее при обновлении. Это тоже решение, и я его, конечно, не отрицаю. Просто я расказал о другом решении.
Ваше решение красивое и оригинальное, но в production я бы его не пустил.
Вы, видимо, что-то упустили из написанного мной. Это, конечно, дело ваше, что пускать в ваш продакшен, а что нет. Закончили.
вообще интересный подход,
хотя это не правильно использовать из nginx напрямую мускуль,
надо сделать простое scgi приложение и в него вписать часть логики. так просто надежнее.
Чтобы преобразовать блокирующий код в неблокирующий, достаточно перехватить блокирующий вызов и заменить его на неблокирующий,…
Скажи кому такое в тёмном переулке — не поймут.
Sign up to leave a comment.

Articles