Как стать автором
Обновить

Комментарии 104

Дочитал до
Зачем мне FastCGI, когда уже есть PHP...
и дальше не стал.

Вы сравниваете кислое с длинным — php замечательно работает с fastCGI, о чем вы можете прочитать, например вот тут
Перед тем как, что-то писать про FastCGI — прочитайте, что такое FastCGI и чем это отличается от CGI. А потом подумайте и скажите — почему то, что вы зазываете FastCGI не настоящий FastCGI. А автор же конечно хотел сказать, зачем ему C++. Любой из этих языков может работать в FastCGI режиме (PHP приэтом нигде так не запускается ибо надо думать головой)
Не портьте мне мой C++ вашим Web'ом!
Наоборот, отлично. Мгновенная обработка страниц на скромных серверах, значительное сокращение времени решения затратных задач, оформление часто изменяющихся параметров, как то счетчики.
Никто не заставляет Вас писать на с++ весь сайт, выносим узкие моменты и радуемся.
>>Выносим узкие моменты и радуемся
узким моментом зачастую бывает работа с БД
FastCGI + C++, какая БД, о чём вы?
Всё в памяти процесса, только хардкор!: )
Я тоже так думал, пока небольшой проектик не стал кушать гигабайты. Пришлось изобретать динамическую загрузку/выгрузку, статистику использования, индексы… В какой-то момент я понял, что изобретаю очередной sqlite или что-то подобное. Не, но фана конечно было много.
Пара гигов памяти под небольшой, но требовательный к скорости проект — мелочи. Если же данных действительно так много, что в память не влезут никак — это уже совсем другая история и другие архитектурные решения :)
Любой проект требователен, вопрос в нагрузке. Задача была сделать систему комментариев/аттачей (как на хабре), после смешных 30к комментариев было решено свернуть лавочку. Т.е. данных в общем-то нет вообще, а память непонятно куда утекла (валгринд показывал, что ничего не течет в плохом смысле). Конечно, вопрос в архитектуре, которую я не осилил.
Не бывает, если БД построена на Redis
К сожалению, на больших нагрузках, редис любит залипать. Первый раз столкнулся, когда попытался заменить им мемкеш для кэширования запросов к базе в проекте с 150 хитов в секунду (5-6 запросов на страницу… к кэшу, естественно, в основном, а не базе).
Судя по бенчмаркам — плевая нагрузка для редиса должна быть, но нет. Так что не нужно рассматривать его как панацею.
Почему не реализовать http интерфейс на с++? Зачем именно fastcgi?
иногда лучше «все лишнее» отдать Apache/nginx
Так отдавайте, nginx и http proxy_pass вам в помощь. Вопрос в том — почему apache/nginx должны связываться по fastcgi, а не http? Намного больше реализаций http интерфейсов, чем fastcgi.
Потому что FastCGI значительно лучше подходит для работы с backend приложениями чем HTTP. Через FastCGI можно передавать служебную информацию, иметь отдельный канал для ошибок, управлять приложением, делать мультиплексирование и многое другое. HTTP разрабатывался для общения клиент-сервер и там нет адекватного способа отделить служебную информацию от того что прислал клиент например.
К сожалению ничего этого не будет работать при такой деревянной реализации FastCGI как описана в этой статье. Мы попытались реализовать весь этот потенциал в Helicon Zoo, но как выяснилось ни один из существующих backend фреймворков не поддерживает полноценно стек FastCGI, а реализует его так же деревянно как описано тут. Так что не для кого стараться пока.
Всё это может делать и http сервер.
мне кажется начинаются религиозные распри… [сколько людей — столько и мнений]

ниже речь пойдет о реализации быстрого приложениия на Сях.

HTTP хорош, надо парсить самому заголовки и делать много нудной работы, есть libevent ( ev_http) нам в помощь. nginx можно использовать как прокси.
Придется самому реализовывать GET/POST маршрутизацию (имеется ввиду вызов необходимых функций в соответстввеее с урлом. ) D libevent HTTP реализован не в полном объеме (кажется нет обработки методов PUT, DELETE, но легко пропатчить ) что затруднительно реализовать RESTFull

FastCGI — тоже хорош, и за тебя разобрали все заголовки, а nginx разберет урл и сделает необходимый роутинг, и все что надо и даже больше (например GeoIP) положили в окружение. Все есть как на блюдечки… Только реализовывай свой бэкенд…
реализация FastCGI можно либо используя либу, можно самостоятельно используя libev/libevent

Лично я предпочитаю scgi — он проще в реализации. Есть либа libscgi, на данный момент меня устраивает, но надо допиливать на неблокируемые соединения [знаю как — но нет времени].

Область применения вышесказаннного — реализация AJAX счетчиков (SCGI), отдача баннернного контента (HTTP), в данном случае url на статический контент. И то и другое стояло за nginx.
1. Добрый вечер.

2. Роутинг в nginx будет работать в обоих случаях — директивы реверс и fastcgi прокси являются уровня Location.

3. Разобранные заголовки от frontend сервера им же складываются в поток байт для передачи по bsd или unix сокетам, что требует такого же парсинга на стороне бекэнда.

4. Nginx в обоих случаях может добавлять к запросу необходимые данные в виде дополнительных заголовков
или переменных fastcgi, что является равнозначным с.п. 3.

5. Религия здесь отсутствует.
Все не правильно — надо связывать все по ZeroMQ как в Mongrel2 :)
а что будет класть данные в 0MQ?
сериализованные запросы?
На входе стоит допустим Mongrel2, потом по 0MQ происходит обмен данных с приложением.
какова скорость реакции Mongrel2?
А что такое «все лишнее», парсинг заголовка запроса? А что еще лишнее? Если головы на плечах не иметь, то и с либой fastcgi можно дыр таких сделать, что мало не покажется. Зато для использования обязательно нужна поддержка со стороны сервера, работать может только с сервером. А взять готовые решения для HTTP протокола и вуаля, вообще делать ничего не надо и может работать самостоятельно без всяких там серверов, а может и за реверс прокси висеть.
Кластеризация прежде всего.
Что кластеризация?
прежде всего
Потому что велосипеды изобретать нет смысла.
Причем тут велосипед? Я про разницу между fastcgi и http демоном на с++.
Ну как сказать… Писать свой демон HTTP — это либо сложно и долго, либо небезопасно и глючно. FastCGI в этом плане лучше подходит на роль интерфейса для программной логики. Исходя из этого я посчитал что лучше уж отдать обработку HTTP чему-то более приспособленному для таких целей.

Производительность, конечно же будет выше в случае «монолитного» демона.
Почему свой? Есть уже тысячи реализаций, написанных до вас. Вопрос про разницу — взять готовую имплементацию fastcgi или готовую исплементацию http?
Потому что настоящий веб-сервер — штука сложная. Пусть постановкой запросов в очередь, безопасностью и т.д. занимается профессионально написанный сервер, а генерацией страниц — простенькая программа, ненамного сложнее PHP-скрипта.
все хором идем учить lua
Была идея писать на С++. Но когда во время работы постоянно сталкиваешься тем что на языке X есть такая-то библиотека для работы с тем-то а на С++ нет, то вскоре понимаешь что это плохая идея
на Си/С++ есть почти все, что нужно в современном WEB
Кстати, есть даже MVC-фреймворк, правда с немного дебильным названием: CPP CMS.
Вот так, с помощью нехитрых приспособлений буханку белого (или черного) хлеба можно превратить в троллейбус… но зачем?

PS. Если уж так свербит писать web на c++ то возьмите хотя бы готовые фреймворки чтобы не изобретать велосипед — www.webtoolkit.eu/wt#/, cppcms.com/wikipp/en/page/main
Вы уверены, что реализация http-сервера в nginx более велосипедна, нежели в представленных Вами поделках?
Почему Вы считаете FastCGI велосипедом, если это давно отработанная технология?
А если на с++ мы напишем счетчик посещения highload проекта, а отображение страниц будет отдано php?
Никто не говоил что FastCGI велосипед, но вот писать с нуля web-обработчик FastCGI запросов на C++ это точно велосипед.
Нет, если вам нужно просто разобраться в технологии вопрос другой, но использовать это в продакшене абослютно нецелесообразно. Что касается счетчика посещений, думаю что вопрос упрется больше в архитектуру нежели в язык реализации.
Велосипеды изобретать бывает полезно, чтобы понять, как они работают.
Не вопрос, если разобраться — я только за.
вот главный вопрос где необходимо остановиться, например, async request handling:
— на уровне библиотеки высокого уровня;
— на уровне библиотеки низкого уровня;
— спуститься еще ниже и написать свой собственный кусок кода для OS;
— написать свою OS.
все зависит от задачи…
думаю что осей хватает под всевозможные задачи, но есть вероятность, что кусок кода под ось написать придется ;)
лично мне больше нравятся cppnetlib + ctemplate. обе открыты, предоставляют лишь базовые интерфейсы, мало жрут ну и в довесок проект можно собирать как под виндой так и под nix системами.
Спасибо, просто замечательное руководство для начинающего! Попадись оно мне раньше :)
Сам писал как-то подобное в такой же связке (C++ + fastCGI + nginX). Так же рассчитывал высокую скорость работы и низкие затраты по памяти. Прошло время, и я понял, что это просто бессмысленно для 99% случаев. Java в сочетании с Jetty, например, помогает сделать всё это на два порядка проще, при этом в скорости не проигрываешь (разве что в памяти, но это отдельный разговор :) ).
Попробуйте Netty, он ещё быстрее и памяти меньше ест.
все замечательно и даже черезчур доходчиво,
именно то что нужно начинающему разработчику

но к сожалению, описание самого протокола FastCGI, я так и не нашел

PS в своих проектах использую scgi, он проще в реализации
> а Apache вынужден создавать новый поток для каждого нового соединения, так что 10 000 потоков — просто фантастика

Можно здесь по подробней (лучше даже конкретную цифру). На сколько я знаю, в Linux форки одного процеса (или потока) могут использовать смежную страницу памяти с кодом, что значит прирост памяти при создании нового потока — это лишь полезная нагрузка нового соединения.
НЛО прилетело и опубликовало эту надпись здесь
Понял.

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

> Например, на 10 000 неактивных HTTP keep-alive соединений Nginx расходует около 2.5M памяти, что вполне реально даже для сравнительно слабой машины, а Apache вынужден создавать новый поток для каждого нового соединения, так что 10 000 потоков — просто фантастика.
Форки и потоки — это фундаментально разные вещи. Потоки шарят между собой все (и код и данные), а форки — это полностью отдельные процессы.

Но суть не в этом, а в том, что 10 000 потоков (или процессов) — это грандиозные затраты на перключение контекста, способные поставить на колени даже сервер о 64х ядрах.

Не зря не рекомендуется запускать потоков больше чем количество ядер.
Вы не совсем правы, если потоки много времени проводят в блокирующих сисколах — то их надо делать больше, чем ядер. Скажем, если каждый поток проводит 50% времени в блокирующих операциях, то надо минимум 48 потоков на 24-ядерной машине, чтобы её нагрузить. Иногда максимальную производительность удаётся получить получить только при нескольких тысячах потоков в тредпуле на 24 ядрах.
Новый поток — сами по себе — оверхед, дело не в том сколько он памяти занимает.
Если быть точным, то потоки одного процесса используют общее адресное пространство; форки же одного и того же процесса формально имеют независимые адресные пространства, но фактически ядро при форке не выполняет дорогостоящую операцию копирования всего АП, а использует механизм copy-on-write, при котором физическое копирование страницы в памяти из АП родительского процесса в АП дочернего происходит только при попытке записи на эту страницу.
Если отключить из апача всё что не надо и поставить mod_cas, то очень даже хорошо всё работает на C++, хоть и геморно.
И тут в тредик врывается github.com/lmovsesjan/Fastcgi-Daemon!

Крайне рекомендую — тредпул и всё необходимое уже сделано, хэлперы для работы с запросом и ответом есть (чтение/установка хэдеров, работа с пост и гет параметрами, куками и т.д.). Для этого фреймворка приложение на плюсах — всего лишь 1 класс, унаследованный от базового. Легко пережёвывает большие нагрузки, своими глазами видел цифру в 30 000 запросов в секунду, и это было реальное приложение, которое делало полезную работу. Проверено десятком проектов Яндекса :)
Последнее изменение в том коде сделано достаточно давно. Просто нечего менять? И автор, похоже, в Яндексе уже не работает — мне письмо вернулось. Интересно, есть ли он на Хабре?
Да, менять особо нечего, редко-редко баги фиксятся и всё. Письма можете мне слать (мыло дам в личке, ежели надо), или сразу пулл-реквесты делать, я умею их принимать в той репке. Илья Голубцов ещё в Яндексе работает, а вот вася свалил, да.
На C++ веб-приложения и прикладные сервера долго не писали и не пишут по одной очень простой причине — неуправляемое окружение. Любой memoryleak, любой сегфолт — и вполне вероятно что ваше приложение рухнет вместе со всей операционкой. Вполне вероятно, что в продакшене. В 3 часа ночи.

Поэтому, историчеки, веб работает на интерпретируемых языках или виртуальных машинах. C++ там лучше не использовать, как и прочие низкоуровневые языки.
А интерпретаторы этих языков пишутся на чем?..
Ключевой момент тут — квалификация писателей интерпретаторов.
А вы обычно нанимаете php-мартышек за еду?
Вы не видите разницы между интерпретаторами, которые пишутся по четким спецификациям и годами не выходят из бет, и бизнес-логикой которая переписывается по сто раз в день?
Если что-то переписывается по 100 раз в день, то из этого вполне может выйти интерпретатор (или даже виртуальная машина).
Ну и мы пришли к тому к чему начали — нужно управляемое и устойчивое окружение. Зачем тогда изобретать велосипед?
Такие вещи как Hight Availability systems и прочие Watchdog'и вам не знакомы? И то, что приложения на интерпретируемых языках не падают — прохладная история.
И на чем же их внезапно пишут? ;))))))))))))))
Гугль говорит, что почему то в основном на вполне виртуальной Java. А местами до сих пор так и вообще на Коболе.

Ключевой момент не в падении, а в последствиях для системы.
Виртуальная машина почистит память и запустит процесс заново.
Протухший указатель в плюсплюсном коде на Ubuntu 12.04 недавно повесил мне иксы.
Кого «их»? Если HA системы, то, например, на моём текущем месте работы — на plain С. Мне трудно представить, что может произойти, что вызовет большие последствия, нежели доли секунды простоя для части клиентов.

Какое отношение имеет userspace Ubuntu 12.04 к HA/real-time системам — ни малейшего представления.
Вы же прекрасно понимаете, что ваше конкретное место работы — далеко не показатель, тем более без озвучивания конкретных задач и выделенных на их решение ресурсов. Ну и я сильно сомневаюсь, что вы там пишете сайты на fastcgi.

Userspace убунты ни при чем. А протухшая память и ошибки разработчиков очень даже.
Ох, а мне было показалось на мгновение, что вы искренне и серьёзно.
Прошу прощения, но придётся сократить рацион, всех благ.
Вы о чем?
Слишком толсто, бро, кушаешь много и неаккуратно.
Отсутствие аргументов уже принято скрывать за обвинениями в троллинге?
Не говоря уже о том, что гугление «Accenture high avalaibility» выдает в основном ту же Java.
Да, стоимость разработчиков и время разработки на Ruby, PHP или Perl будет меньше. Но если нужна высокая производительность — то придется платить хорошему С++ программисту, который пишет код без утечек памяти и проверяет продукт утилитами, следящими за валидностью доступа к памяти. Дать этому программисту больше времени, ибо на С++ кода придется написать больше.
Вопрос простой — что дешевле докупить оборудования (если продукт легко масштабируется, что бывает не всегда) или заплатить больше за разработку.
Кому нужна настолько высокая производительность на application-слое веб-приложения? ;)
Не окупится никогда. Эти ресурсы нужно пускать на оптимизацию базы и фоновых процессов, эффекта будет гораздо больше.
Есть небольшая такая разница в аренде 100 серверов и 500 серверов.
Есть небольшая такая разница в нагрузке на разные слои. Вы не увидите разницы в несколько миллисекунд, если выборка из базы работает секунды.
А вы сделайте базу быстрой, тогда тормозить будет шаблонизатор.
> Любой memoryleak, любой сегфолт — и вполне вероятно что ваше приложение рухнет вместе со всей операционкой

Либо у вас сервера работают под MSDOS либо вы еще не узнали что у современных операционок есть виртуальная память. Memory leak в пользовательском процессе не заставит рухнуть всю операционку.
Обратите внимание на слово «исторически». Ну и сегфолты пока никто не отменял.
image

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

Вы не сравнивайте всякий гавнокодинг скриптиков школотой и написание нормальных быстрых framework'ов и высоконагруженных сервисов.
Вы серьезно не видите разницы между «веб-приложениями и прикладными серверами» и автоматизацией хостинга? ;)))))
НЛО прилетело и опубликовало эту надпись здесь
Все эти проблемы — плата за гибкость, которой хочет клиент. У cPanel есть свой набор ПО, с которым они работают, а панели ISPsystem позволяют поставить то, что хочется использовать каждому в отдельности.
При всё этом система переносов работает достаточно стабильно. Вы можете себе представить сколько различных случаев и проблем учитывается в ней, при свободе выбора ПО для работы?

Вообще, это топик не о миграции в ISPmanager, а о языках.
НЛО прилетело и опубликовало эту надпись здесь
А где же обещанный в названии С++? Даже встретив struct я еще на что-то надеялся ;)

Увы.
А g-wan кто-нибудь пробовал использовать?
К сожалению, протекает и падает, завести тоже не тривиально.
Ну как сказать, самому по долгу службы приходится иметь дело с FastCGI на C++. Но я бы хотел вас обрадовать, используя boost::asio реализация будет в разы проще, при этом это будет полноценный сервер, который работает по HTTP протоколу. Опять же модуль для nginx/apache реализовать не сложнее (хотя для nginx придется поковыряться в исходах), чем реализовать FastCGI демон, но при этом будет заметно эффективнее. Конечно nginx и apache не позволят работать многопоточно (но и часто нет смысла в многопоточности, сложность синхронизации даст о себе знать, а в неумелых руках может привести и к падению производительности, в сравнении с тем же кол-вом процессов).

Опять же вся разница в FastCGI и собственной реализацией HTTP протокола заключается в некоторой дополнительной более или менее безопасной прослойке, которая распарсит частично заголовок и прокинет в виде переменных окружения, реализовать свой парсинг этих данных дело не более чем одного дня, а запрятать можно за тем же nginx. А если еще взять за основу пример из boost::asio который частично реализует работу с HTTP протоколом, будет совсем легко.

И кстати да, где C++? Вижу только C.
Взгляд зацепился за

Второе, о чём Вы должны помнить — динамическая типизация и сборщик мусора занимают много ресурсов. Иногда — очень много. Например, массивы целых чисел в PHP занимают примерно в 18 раз больше памяти (до 35 раз в зависимости от различных параметров компиляции PHP), чем в C/C++ для того же объема данных, поэтому задумайтесь о накладных расходах для сравнительно больших структур данных.

Массивы в PHP — это ведь хэш-таблицы со значениями — указателями? Динамическая типизация и сборщик мусора никакого отношения к тому, что они занимают больше памяти, не имеют. Массив чисел в C обычно в совсем другой структуре данных хранятся, вот и все. Хэш-таблица со значениями-указателями и в C/C++ будет много места занимать. Тут не в языке дело, а в выборе структуры данных.

В динамических языках тоже есть возможность выбирать структуры данных (и создавать свои). Например, в питоне есть тип list — это массив указателей, по сути. А есть array.array — это одномерный массив чисел. И вот array.array будет столько же места в памяти занимать, сколько и соответствующий ему массив на C. На создание объекта array.array есть небольшие накладные расходы (порядка 50 байт, чтоб завернуть в объект), но это совершенно не важно именно для «больших структур данных» — какая разница, 50 + N*sizeof(elem) или N*sizeof(elem).

В php наверное что-то похожее тоже есть, но не спец тут.
Нет похожего в PHP. Все пользовательские структуры данных имеют динамически типизируемые элементы, а значит занимают много больше памяти, чем требуется для хранения значения элемента — как минимум хранение его типа необходимо, не говоря о резервировании памяти под значения большего размера, чтобы при изменении типа не выделять память по новой. А list и array.array в Python (если допустить что их по памяти хорошо оптимизировали), хранят значения только одного типа и на указание типа каждого элемента память не тратится (в случае list имею в виду указатели на значения, сами значения хранят свой тип).
Кроме fastcgi существует незаслуженно мало упоминаемый scgi. Это более лёгкая версия fastcgi, которая к тому же быстрее парсится. Тем, кто планирует действительно эффективные backend-ы, рекомендую обдумать этот вариант.
Подскажите, пожалуйста, где найти информацию по scgi? Интересует описание протокола, примеры использования, существующие реализации (желательно — на C, но другие языки тоже интересны).
Поправьте пожалуйста пост, правильные параметры компилятора: gcc: -lfcgi и -lpthread
За статью спасибо.
Спасибо за уточнение, статью поправил.
Нельзя ли написать реализацию для нескольких ip адресов в библиотеке libfcgi?
Соответственно, надо найти место где парсится адрес от порта в int FCGX_OpenSocket(const char* path, int) и наверняка адрес пишется в какую то переменную char*, вместо неё завести переменную set<char*>, далее запустить компиляцию libfcgi, далее идти по местам ошибок компиляции и действовать по смыслу, скорее всего заменять проверку на проверку в цикле.
Сокеты Беркли для tcp позволяют узнать адрес инициатора у accept-сокета в аргументе cliaddr
для udp — используя функцию recvfrom. По классике в сокетах Беркли recvfrom нет, Но она по-моему на всех платформах реализована, в линуха уж точно есть. И уж наверняка юзается в libfcgi. Они правда могли биндить и при биндинге указать допустимый адрес.
Короче полюбасе надо бы такую штуку провернуть, заодно покурив мануалы по сокетам.
НЛО прилетело и опубликовало эту надпись здесь
И вот я столкнулся с Libfcgi по работе.
Необходимо написать сервис, который будет раздавать mpeg-ts по http.
mpeg-ts — бесконечен, это просто онлайн трансляция чего либо.

Но есть один нюанс: подключений может быть сколько угодно.

А тут получается, что я не могу в одном потоке начать новый request (typeof FCGX_Request ) не закончив старый, так как завершить соединение я могу только когда клиент отрубился или сервис остановился. (я ведь отдаю части Mpeg-ts по этому request'у)
Получается, что я должен заранее знать, сколько подключений будет и создать для каждого одновременного подключения свой поток со своим экземпляром FCGX_Request, что совсем не айс.

Тупиковая ситуация.
Пытаюсь запустить все это под виндой и OpenServer'ом, что-то уперся в самый последний шаг — как заставить все это работать вместе:)
Программу и необходимые ей библиотеки собрал под Visual Studio, программа запускается, начинает слушать порты… nginx тоже есть, конфиг ваш взял — а по localhost'у ничего…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории