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

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

Могу что-то напутать, но в nginx по моему есть переменные схожие по названию с директивами которые ограничивают скорость, и если их прописать то ваша проблема решается.
Боюсь вы ошибаетесь, Nginx не умеет ограничивать скорость для IP, только на отдельное соединение. Предполагаю что вы подумали про это:

    if ($slow) {
        set $limit_rate 4k;
    }

Выдержка из документации: Ограничение устанавливается на запрос, поэтому, если клиент одновременно откроет два соединения, суммарная скорость будет вдвое выше заданного ограничения.
То есть документация врёт? Или я неправильно её понял?

If it is necessary to limit speed for the part of the clients at the server level, based on some kind of condition — then this directive does not apply. Instead you should specify the limit by assigning the value to the $limit_rate variable, as shown below:

server {
  if ($slow) {
    set $limit_rate  4k;
  }
}


wiki.nginx.org/HttpCoreModule#limit_rate
чуть выше написано:

Limitation works only for one connection, i.e., if client opens 2 connections, then total velocity will be 2 times higher then the limit set.
Вот так и получается, что многие используют set $limit_rate наивно полагая что ограничили максимальную скорость для клиента вне зависимости от того в 1 поток он качает или в 10. А потом жалуются что какой-то пятиклассник забил им канал качая в 10 потоков Звездные Войны в Blu-Ray формате…
Всё, понял. Спасибо. Думал, что это только к директиве limit_rate относится, но не к переменной
Не ограничивают скорость на ip потому, что через него может качать много пользователей (NAT). Правильно — генерировать пользователю уникальную ссылку (возможно, которая будет работать только с определенного ip) и ограничивать скорость для нее (вне зависимости от числа соединений).
О чём речь? Как раз таки Nginx этого и не умеет, он не умеет ограничивать скорость ни на домен, ни на ссылку, ни по IP клиента. Вернее он делает это, но только на каждый отдельный запрос (соединение). А извращаться с отдачей через PHP или ограничивать клиента одним соединением на IP или пусть даже на сгенерированную ссылку — это костыли. Описанный в статье модуль как раз таки решает данную проблему ограничивая скорость по IP.

Не ограничивают скорость на ip потому... Вы про разработчиков Nginx? Если они сознательно что-то не хотят делать в силу своих убеждений, это вовсе не значит что это не надо пользователям их программного продукта.
Идея очень правильная, но как это сделать?
Установить описанный в статье модуль и ограничивать скорость для нее (вне зависимости от числа соединений), как сказал esc. Без этого модуля Nginx попросту не сможет ограничивать скорость вне зависимости от числа соединений, он этого попросту не умеет.
Это понятно. Я подумал, что можно сделать без этого модуля.
добавлять в ссылку уникальный хешь, по которому ограничивать количество одновременных соединений и пользоваться уже строенными средствами ограничения скорости, а вот для такого ограничения вам скорее всего все равно понадобится какая-то логика внутри конфига.
НЛО прилетело и опубликовало эту надпись здесь
Я Вам раскрою страшную тайну: эта страшная команда лежит в основе любого линукса, так что не стоит так остро реагировать.
Вот только под Linux в последние лет 10 я применяю её не чаще пары раз в год и в весьма специфических задачах :) На дворе XXI век, всё же…
Ну многие вообще под виндой сидят. При чем тут век? Я вот косвенно ее применяю раз 10 в неделю и 2-3 напрямую.
Это был намёк на то, что в нормальных Linux-дистрибутивах в этом веке обычно нужно очень мало делать руками. И потому существует масса пользователей, которые к ./configure могут относится нервно :)



Более того. Сегодня считается хорошим тоном на боевом сервере не держать девелоперскую подсистему. Так что ./configure на продакшне может просто не сработать :)
Про source-based дистрибутивы слышали? При должном умении на них ставятся отличные информационные системы.

А еще бывают такие люди разработчики. И бывает у них тоже Linux.

К тому же оно open source, что как бы намекает. Что иногда бывает компиляция из исходников.

Я к тому что это ни разу не устаревшая и применяемая многими людьми команда.
Представьте себе, я 10 лет (в аккурат с 1994-го) сижу на на Gentoo. И именно на ней мне, как раз, не приходится запускать configure :) Я же писал, XXI век на дворе…

Это не говоря уже про то, что я именно разработчик, и Linux до последнего года был основной системой :) Только сейчас, по мере окончательного угасания Gentoo, на десктопе пересаживаюсь на Windows.

Я к тому что это ни разу не устаревшая и применяемая многими людьми команда.

Я этого не утверждал. Я просто говорил, что это в наше время эта команда может быть далеко скрыта даже от весьма продвинутого пользователя. Кроме того, как писал в выше заминусованном сообщении, хорошая практика Web-продакшна (а иначе зачем нам говорить про тонкую оптимизацию nginx?) зачастую исключает наличие средств разработки из соображений безопасности. Лично я именно так и воспринял сообщение автора, породившего эту цепочку. Там, где стоит вопрос безопасности, вопрос ./configure на боевом сервере уже отчасти оксюморон :)
Пардон, с 2004-го :)
Вот да, а был бы не gentoo а debian, то мог бы быть и 1994.
Моим первым Linux-дистрибутивом был RedHat (5.x какой-то) в примерно 1997-м :) В 1994-м — это совсем экстремально :D
Ну я для неразведения холивара пропущу спорный кусок про угасание генты.

Но расскажите же мне, пожалуйста, с вершины Вашего опыта, чем же configure, make или gcc лично Вам кажутся менее безопасными, чем python, perl или php?

И что мешает человеку, обладающему достаточными навыками, чтоб пробить Ваш сервер до получения локального доступа залить туда то самое сборочное окружение?
А более опытные товарищи поменяли опции в настройках сборки своего пакета nginx'а в CI, откуда он попадает на свой собственный миррор, откуда мирно расползается yum/apt'ами по серверам.
НЛО прилетело и опубликовало эту надпись здесь
у nginx бешеная производительность при минимуме потребляемых ресурсов
НЛО прилетело и опубликовало эту надпись здесь
Какой Апач, вы о чем? Ни разу не ставил Апач за нджинкс. Python & ruby сейчас обычно стартуют на gunicorn/unicorn, php вроде на php fpm или что типа того.
НЛО прилетело и опубликовало эту надпись здесь
lighttpd очень похож на nginx, та же асинхронная обработка запросов и бешеная производительность…
Все же nginx чуть лучше — более оптимальные алгоритмы, меньше load average на равных нагрузках… в общем несколько мелочей :)
Хотя согласен что более «удобное» конфигурирование могло бы склонить чашу весов в пользу lighttpd, однако тут на сцену выходит привычка, для которой все конфиги вроде бы достаточно удобны.
Я на lighttpd просидел 9 лет. Но с прошлого года начал понемногу все свои сервисы переводить на nginx (сейчас только два с Лайти осталось). Производительность у nginx сейчас стала немного выше (хотя раньше было иначе), но дело не в ней. nginx гораздо гибче, мощнее и проще в конфигурировании. lighttpd пока объективно обходит nginx только наличием встроенного fcgi-менеджера. Но с появлением php-fpm, встроенный fcgi сейчас довольно мало востребован.
НЛО прилетело и опубликовало эту надпись здесь
Хотелось бы немного о принципе работы и использовании:
на чем основано ограничение? Какие-то внутренние фишки nginx, или свой кроссзапросный метод?
тестировали?
как точно ограничивает?
увеличивает ли latency?
в общем. поделитесь впечатлениями :)
Смотрите, Nginx лимитирует скорость для каждого запроса примерно так (мои предположения):

r->main->limit_rate = $limit_rate; (а именно $limit_rate указанный в конфиге запрошенного location или хоста)

Модуль представленный в статье так же лимитирует скорость каждого запроса (соединения), но несколько иначе, вот выдержка прямо из кода модуля:

speed = lscf->speed; r->main->limit_rate = speed / ls->conn; (а именно limit_speed указанный для зоны в конфиге запрошенного location или хоста)

т.е. скорость делится на количество текущих соединений с сервером. Как видите всё предельно просто.

Более того, поскольку используются зоны, то вместо $binary_remote_addr можно использовать всё что угодно для создания нужной зоны ограничений. Можно установить лимиты на домен, страну (geoip), да хоть по имени браузера или зарезать скорость для Googlebot.

Модуль используется с ноября 2013 года на нескольких серверах, всё работает на ура, никаких сбоев не было. Буквально вчера собрал на очередном сервере Nginx 1.6.0 (последняя версия) с этим модулем (поэтому и решил написать статью, уж больно модуль хороший). Хотя признаюсь — модуль совершенно неизвестный от сомнительного китайского товарища, но на практике претензий к нему нет. Всевозможные конфигурации и ситуации конечно не тестировались, поэтому подводные камни могут быть, но исправить ошибку может любой — да здравствует opensource.
Правильно ли я понимаю, что если вы выставили суммарный лимит на скорость 100k и, по доброте душевной, разрешили делать до 100 соедиений, то у вас по каждому соединению будет жесткий лимит 1k. Соответственно если пользователь будет использовать всего одно соединение, то он всё равно будет качать на скорости лишь 1к, а не 100к. Или же ls->conn — это _текущее_ количество соединений?
да, это меня тоже смутило :)
хотя нет, конечно же это текущее количество соединений, но все равно алгоритм какой-то слишком прямолинейный.
Если мы делаем несколько различных запросов — то ограничение всегда будет меньше, потому что соединения не утилизируются полностью
насколько я понял, красно-черное дерево используется как раз для хранения информации о соединениях
Марихуана? ЛСД? Бросайте… Если установлено ограничение в 100к и пользователь качает в 1 поток, то у него будет скорость 100k. Выше представлена формула вычисления скорости, разделите 100/1 и подумайте что получится.
Эээ, вы хоть до конца читали-то мой комментарий? )

В любом случае, ограничению скорости по этой формуле очень далеко до «правильного». Скорее всего в nginx ограничения не делали как раз по той причине, что правильно сделать ограничение по сумме не так-то просто (особенно с учетом того, что придется выбирать, какому из соединений пользователя резать скорость в текущий момент).
Дочитал. А вы в свою очередь читали мой комментарий? По моему про speed / ls->conn там предельно понятно всё написано — скорость делится на количество текущих соединений с сервером. И после этого вы спрашиваете: Или же ls->conn — это _текущее_ количество соединений?

Это лишь ваше мнение, что чему-то там далеко до правильного. Я так не считаю. Про какие-то там выборы соединений пользователя так вообще чушь, нигде ничего выбирать не требуется, ограничиваются все подключения разом. Модуль предельно чётко и прозрачно регулирует скорость и это именно то, что так давно ждали от Nginx. Данную функциональность в Nginx не вводили только лишь потому, что разработчики мало ориентированы на те нововведения, которые не нужны и не интересны им самим, а так же потому, что разработчиков (помимо Игоря Сысоева) до недавнего времени там было 1-2 человека (а может и сейчас столько) и в таком формате довольно тяжело реагировать на все «хотелки» пользователей.
Это лишь ваше мнение, что чему-то там далеко до правильного. Я так не считаю.
Описанная схема более-менее хорошо работает, когда все соединения равноценным между собой и, например, пользователь просто качает большие файлы. Но как-только появляется какая-либо ассиметрия, то начинаются проблемы.

Поясню на примерах.
Пусть у нас выстален общий лимит 100k.

Кейс 1:
Пользователь качает два файла, по одному соденинению каждый. Лимит скорости на соединение получается 50k. 50k*2=100k.
Всё ОК.

Кейс 2:
Помимо двух скачивания двух файлов пользователь начинает активно ходить по сайту. Пусть бразуер пользователя использует 6 соединений для параллельного скачивания контента: страницы, JS-скрипты, CSS-файлы, прочее. Реальная скорость по этим соединениям может быть невысокой, но не из-за лимита, а из-за того, что сервер не так быстро отвечает либо браузер делает запросы не один за другим, а с паузами (в частности потому, что должен выполнять JS последовательно). А еще есть keep alive, который соединение держит, но скорость передачи по нему может быть 0. Допустим по этим 6 соединениям реальная средняя скорость — 5k. 2+6=8 соединений всего, 100k/8=12.5k лимит скорости, выставляемый обсуждаемым модулем. 2 соединения качают файлы, так что они будут утилизировать этот лимит полностью, а вот остальные соединения — нет. Итого получаем, что общий реальный лимит на соединения от пользователя получился 2*12.5 + 6*5 = 55k, хотя в конфиге вы выставили лимит 100k.
Вот поэтому есть большие сомнения по поводу «правильности» данного подхода.
Если у администратора нет мозгов, то может он и сделает так, как вы тут всё описали. В нормальной ситуации ограничение будет выставлено только на location откуда загружаются файлы, например location /download/ {… }, соответственно серверу будет глубоко до лампочки какие ещё у пользователя открыты соединения, сколько их и что он там загружает (html, css, js и т.д.). Использовать данный модуль для ограничение скорости доступа ко всему сайту — это глупость ввиду описанных вами причин, он не для этого создан.
Добавлю. Возможно вы подумали, что при ограничении скорости учитываются вообще ВСЕ подключения к серверу, однако это не так. Учитываются конечно же только те соединения, которые установлены клиентом с тем location где прописан лимит. Т.е. если я качаю файл из ограниченного по скорости файлохранилища в 10 потоков и имеют 10к на поток (100k/10), а потом решил еще с форума на сайте скачать архивчик на пару гигабайт и тоже в 10 потоков, то мои первые 10 потоков из файлохранилища будут иметь ту же скорость (она не изменится), в то время как с форума я буду качать без ограничений в 10 потоков на максимальной скорости.
Наивный до простоты вопрос — а зачем вообще ограничивать скорость для пользователя? Если у пользователя 100мбит — пусть качает на все 100. Если 1ГБит — пусть тоже себе качает.

Я так понимаю больше важен вопрос, чтобы если другие пользователи с менее широким каналом в этот момент заходили, не испытывали дискомфорта (сначала маленьким, чтобы не обидеть, а излишки — толстым ребятам). Но если возможность и положение звезд позволяет отдавать контент на полную катушку — зачем кого-то ограничивать?
Чтобы не забывали страдать. Ну и ещё потому, что шейпинг траффика — это ужасно сложно.

(сарказм по вкусу).
Сколько угодно причин можно придумать — тонкий канал (дешевая или вообще бесплатная VPS к примеру), перегруженный канал, ddos, файлообменные сервисы, premium загрузки (остальным минимум скорости), нашествие GoogleBot, YandexBot и прочих сканеров или пауков, банальное желание ЧЕСТНО порезать скорость под свои нужды. Да вообще мало ли для чего люди используют лимиты, если бы урезание скорости не было востребовано, то даже $limit_rate в Nginx наверное бы не было, однако же оно есть.
Вот честно обидно за open source.

Всякие «авторы» таких статей, которые немощные, чтобы сделать хоть что-то своими руками, начинают гнать на авторов весьма качественного кода, что они что-то не сделали, не покрыли какой то юзкейс…

Лучше бы пошел да помог и законтрибтил (если уж так все просто как говоришь в топике)

Вместо йуха: nginx.org/en/docs/contributing_changes.html
Есть мнение, что nginx очень недоброжелательно относится к таким вот коммитам стороннего кода. Помню, на это постоянно жаловался товарищ catap, написавший множество модулей, как я понимаю, для mail.ru, об этом часто говорили на форумах, где авторы показывали свои модули, мы тоже пытались туда кое-каких фичи, но не получив ни ответа ни привета, забили.

Такое чувство, что кроме личных знакоый Сысоева, никто в nginx добавить ничего не может. Ну или вероятность этого очень маленькая.
Форкните nginx и поддерживайте свой nginx-ng. Если сможете, конечно.
С точки зрения админа могу сказать, что подавляющее большинство сторонних модулей написано как курица лапой. Сегфолты, утекающая память, непонятно откуда берущиеся тормоза и прочие вкусности достанутся вам бесплатно.
Nginx не является веб-сервером общего назначения, многих фич в нём нет, потому что это не его задача. Никто же не плачет, что в нём нету mod_php.
А чем отличается свой nginx от модулей? Тем, что замораживается версия? Даже не знаю, что лучше, использовать старый nginx и не задумываться об этом или обнаружить, что какие-то модули с новой версией не работают. Как по мне, второе более информативно и более явно указывает на проблему и «куда копать».

Про нестабильность модулей и желание внедрить mod_php это вы сами додумали. То, что мы хотели законтрибьютить относилось к расширенной риалтаймовой статистике. Типа той, что есть у лайти и вместо которой у nginx куцый stub_status. Работает под очень высокими нагрузками и долгое время. Но интереса авторой nginx не вызвало. Потому, сделали свой модуль и чиним, если ломается совместимость с новыми версиями ядра nginx
Так вы делаете как раз то, о чём я говорю.
Только в отличие от полноценного форка вы периодически забираете код из апстрима и адаптируете свой код к новому коду из апстрима.
Я тоже так делаю. Все так делают. Это нормально же.

Но если вы недовольны поведением апстрима «АААА, они не взяли мой суперкрутой модуль», то не стоит на это обижаться. Это опенсорс. Недоволен — форкай и поддерживай сам, если будешь умницей — может быть, даже затмишь апстрим.

Существует TEngine и OpenResty, которые не ругаются на команду nginx, а просто делают то, что хотят.
Я не недоволен, я еще до начала разработки знал как обстоят дела со сторонним кодом в nginx. Я объясняю, почему люди делают модули, а не контрибьютят в основной репозиторий, как возмущается человек выше, дающий ссылку на nginx.org/en/docs/contributing_changes.html
И все же — как быть пользователям за NAT-ом после установки данного модуля на сервере? Один клиент забьет собой весь канал и остальным на сервер не пробиться?

Сколько угодно причин можно придумать — тонкий канал (дешевая или вообще бесплатная VPS к примеру)

тонкий канал — это по-любому плохо, ну будет у 1000 пользователей загрузка по 1кб\сек, они вообще все плюнут и оборвут закачку…

нашествие GoogleBot, YandexBot и прочих сканеров или пауков

какой-то Delirium tremens прям…

ddos

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

По поводу тонкого канала — допустим у меня Гбод на сервере, некто Вася имеет гигабитный линк и забивает мне весь канал…
Я рассчитываю на обслуживание минимального пула в. скажем для ровного счета, 256 клиентов… ставлю ограничение на 4Мбод и канал будет забит только при одновременном приходе более 256клиентов…

В общем, логика примерна такая…
Хм, а TCP сам не разделит скорость между Васей и остальными пропорционально их возможностям? Если нет других клиентов, то какой смысл мучать Васю? Ну разве что, если канал какой-то жлобский и лимитированный. Только вот поможет это только если Вася решит плюнуть и оборвать соединение. А если нет, то он все равно скачает то, что и планировал. Только вместо пары минут будет висеть несколько часов и отъедать часть скорости у остальных, когда их число превысит 256.

Ограничение скорости — тупиковый путь. Вы так ничего не выиграете. Единственная, пожалуй, причина ограничивать, это если вы доступ на полной скорости продаете за отдельные деньги.

Еще может быть актуально для онлайн-видео (псевдостриминг), но там нужен более интеллектуальный алгоритм, а не просто тупое ограничение на Х мегабит.
НЛО прилетело и опубликовало эту надпись здесь
$limit_rate + iptables
Первое ограничивает скорость соединения.
Второе ограничивает количество соединений.

Для больших проектов такое решение не подойдёт, т.к. вызовет грусть у пользователей с серыми IP, но вполне себе для тех, кто раздаёт звёздных войн через nginx.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории