Pull to refresh

Comments 104

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

Вы сравниваете кислое с длинным — php замечательно работает с fastCGI, о чем вы можете прочитать, например вот тут
Перед тем как, что-то писать про FastCGI — прочитайте, что такое FastCGI и чем это отличается от CGI. А потом подумайте и скажите — почему то, что вы зазываете FastCGI не настоящий FastCGI. А автор же конечно хотел сказать, зачем ему C++. Любой из этих языков может работать в FastCGI режиме (PHP приэтом нигде так не запускается ибо надо думать головой)
Наоборот, отлично. Мгновенная обработка страниц на скромных серверах, значительное сокращение времени решения затратных задач, оформление часто изменяющихся параметров, как то счетчики.
Никто не заставляет Вас писать на с++ весь сайт, выносим узкие моменты и радуемся.
>>Выносим узкие моменты и радуемся
узким моментом зачастую бывает работа с БД
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 форки одного процеса (или потока) могут использовать смежную страницу памяти с кодом, что значит прирост памяти при создании нового потока — это лишь полезная нагрузка нового соединения.
UFO just landed and posted this here
Понял.

Просто в тексте звучит так, как будто именно памяти 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'ов и высоконагруженных сервисов.
Вы серьезно не видите разницы между «веб-приложениями и прикладными серверами» и автоматизацией хостинга? ;)))))
UFO just landed and posted this here
Все эти проблемы — плата за гибкость, которой хочет клиент. У cPanel есть свой набор ПО, с которым они работают, а панели ISPsystem позволяют поставить то, что хочется использовать каждому в отдельности.
При всё этом система переносов работает достаточно стабильно. Вы можете себе представить сколько различных случаев и проблем учитывается в ней, при свободе выбора ПО для работы?

Вообще, это топик не о миграции в ISPmanager, а о языках.
UFO just landed and posted this here
А где же обещанный в названии С++? Даже встретив struct я еще на что-то надеялся ;)

Увы.
К сожалению, протекает и падает, завести тоже не тривиально.
Ну как сказать, самому по долгу службы приходится иметь дело с 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. Они правда могли биндить и при биндинге указать допустимый адрес.
Короче полюбасе надо бы такую штуку провернуть, заодно покурив мануалы по сокетам.
UFO just landed and posted this here
И вот я столкнулся с Libfcgi по работе.
Необходимо написать сервис, который будет раздавать mpeg-ts по http.
mpeg-ts — бесконечен, это просто онлайн трансляция чего либо.

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

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

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

Articles