«Node js & Подключение модулей без явного использования require или аналог namespace» и «Причесываем трафик — динамический шейпер на Linux Linux*»: разница между страницами

Материал из support.qbpro.ru
(Различия между страницами)
imported>Vix
Нет описания правки
 
imported>Vix
(Новая страница: «Предположим у вас есть домашняя сеть (или не домашняя, а сеть небольшого офиса) с выходом …»)
 
Строка 1: Строка 1:
При работе с node.js часто приходится подключать файлы, расположенные не в
Предположим у вас есть домашняя сеть (или не домашняя, а сеть небольшого офиса) с выходом в интернет через не очень скоростной канал. А пользователей — много, и каждый хочет что-то скачивать, да с максимальной скоростью. Вот тут перед нами встатет задача, как максимально эффективно распределить наш интернет-канал между пользователями так, чтобы они не мешали друг другу. В этой статье я опишу, как можно решить такую задачу с помощью Linux-сервера.
текущей директории, и даже не в поддереве текущего каталога. Поэтому часто в
модулях можно наблюдать что-то вроде


var obj = require('../../../a/b/c/someModule');
Сформулируем, что же мы хотим получить в результате:
1. Чтобы канал поровну делился между пользователями.
2. Чтобы канал зря не простаивал.
3. Чтобы онлайн-игры, ssh и telnet не «лагали» даже при полной загрузке канала, например торрентами.




Для меня гораздо удобнее подключать файлы относительно корня проекта (модуля),
Если интернетом будут одновременно пользоваться 10 пользователей — каждый получит в свое распоряжение 1/10 часть канала, если в данный момент активен только один пользователь — он будет использовать весь канал сам.
например
Добиться этого можно используя планировщик пакетов HTB, который входит в ядро linux начиная с версии 2.4.20.
image
Можно конфигурировать шейпер с помощью команды tc, но для более удобной и наглядной настройки я рекомендую скачать скрипт htb.init. Они использует для конфигурации htb набор конфигурационных файлов, именуемых так, что при сортировке по алфавиту их имена позволяют визуально представить себе дерево классов шейпера и удобно его редактировать.
Предположим, что у нас на сервере есть интерфейс eth0, через который мы подключены к интернет, и eth1, который «смотрит» в локальную сеть.


var obj = require(base_dir + '/a/b/c/someModule');
Управлять можно только исходящим из интерфейса трафиком, поэтому для eth0 будут правила для upload трафика пользователей, а для — eth1 — download трафика.


По умолчанию конфигурационные файлы htb.init находятся в /etc/htb/. Для начала напишем правила шейпинга для upload трафика, они у нас будут простые.
Создаем файл с именем eth0 (интерейс «смотрящий» в интернет), в него напищем следующие строки:
DEFAULT=20
R2Q=1


Однако и в этом случае довольно много писанины и необходимо откуда-то получать
Параметр DEFAULT задает номер класса, к которому будет относиться трафик «по умолчанию» — обычно это класс с минимальным приоритетом. Параметр R2Q влияет на работу алгоритма разделения канала и зависит от ширины канала. Я подбирал его значение эмпирическим путем, для моего исходящего канала в 2 Mbit.
base_dir.
Для себя я нашел решение проблемы, позволяющее больше не писать require и не
узнавать base_dir:


var obj = lib.a.b.c.someModule;
Далее, создадим файл eth0-2.full2MBit, для класса включающего в себя весь доступный интернет-канал. Имя файла состоит из имени интерфейса и id класса, после точки идет смысловое имя класса, используется как комментарий и системой игнорируется.
RATE=2Mbit
CEIL=2Mbit


RATE — это наша гарантированная полоса, CEIL — максимальная полоса. Так как у меня канал с гарантированной максимальной полосой в 2 Mbit, то эти параметры у меня равны.


Теперь мы создадим по одному файлу для каждого класса трафика, который у нас будет. Я у себя создал отдельные классы для ssh трафика, а так же трафика игр World Of Warcraft и Counter Strike, хотя вы можете сделать для всего высокоприоритетного трафика один класс.


Идея решения
Пример для ssh — создаем файл eth0-2:10.ssh. В имени файла через двоеточие указан id родительского класса 2 и id текущего класса — 10. Идентификаторы для класса вы можете выбирать произвольно.
# class for outgoing ssh
RATE=128Kbit
CEIL=2Mbit
RULE=*:22
PRIO=1
BURST=100Kb


В параметре RATE указана гарантированная полоса для этого класса, в CEIL — максимальная. Мы выделяем для ssh 128 KBit (как минимум) и разрешаем ему загрузить весь канал (я закачивать файлы по sftp). PRIO задает приоритет класса трафика (1- максимальный, чем больше число — тем меньш приоритет). BURST задает максимальный объем трафика, который будет передан на максимальной скорости перед тем, как перейти к передаче данных из дургих классов. Установив этот параметр в достаточно высокое значение мы добиваемся того, что трафик ssh будет передан с минимальными задержками.
RULE задает правило, по которому будет отбираться трафик в этот класс.
Формат — RULE=[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]]
Обратите внимание на запятую! RULE=*:22 обозначает трафик, у которого порт назначения 22, а RULE=*:22, обозначает трафик, у которого исходящий порт — 22.


Решение проблемы — создание хитрого «класса» (да простят меня гуру javascript за
Создадим так же классы для других видов трафика, и класс для трафика «по умолчанию» с id 20 (мы указали вначале что именно в класс номер 20 надо направлять трафик «по умолчанию»). В нем укажем используемую дисциплину разделения канала LEAF=sfq, для того чтобы upload поровну делился между TCP сессиями разных пользователей.
такое слово), свойствами которого являются директории и файлы указанной при
создании класса директории. Если свойство-директория не является модулем, то
данное свойство также является объектом нашего класса, свойствами которого
являются директории и файлы этой директории.


Чтобы стало понятнее приведу пример. Предположим у нас имеется следующая
Для eth1 правила будут почти такие же, только с учетом что общая ширина канала 100 Mbit, мы ведь хотим чтобы можно было обращаться к локальным ресурсам сервера на полной скорости, для интернет-трафика выделен отдельный класс на 2 MBit, у которого как потомки добавлены классы отдельных пользователей, разделение по классам я делал по IP адресам. Для каждого пользователя можно указать максимальную и гарантированную скорость, а так же приоритет.
структура проекта:


После правки конфигурации перезапускаем htb.init:
/etc/init.d/htb.init restart
И правила шейпинга трафика сразу же вступают в силу.


Содержимое файлов:
В процессе состевления правил обычно возникает необходимость как-то визуализировать трафик, в целях отладки и мониторинга, поэтому решил написать плагин для системы мониторинга серверов munin, который бы визуализировал распределение по классам HTB трафика. Выводить решил загрузку только классов-листьев дерева, так как именно они обычно несут смысловую нагрузку.
  \a\b\Foo.js
Скачать плагин вы можете из официального репозитория плагинов munin, называется он qos_, просто скопируйте его в папку плагинов munin /usr/share/munin/plugins/ и в папке используемых плагинов /etc/munin/plugins сделайте на него символическую ссылку вида qos_eth1, где eth1 — имя интерфейса, на котором нужно мониторить загрузку.
  \a\c\Bar.js
В файле конфигурации плагинов можно добавить следущее:
  \a\index.js
  [qos_eth1]
env.ignore_queue1_10 yes
  env.label_name1_31 Viperet
  env.label_name1_32 Cornet


var LazyLoader = require('./LazyLoader');
Параметр env.ignore_queue позволяет не отображать на графике состояние класса с указанным id, а параметр env.label_name — задать человекопонятную метку для класса на графике.
global.lib = new LazyLoader(__dirname); 
var foo = new lib.a.b.Foo();
console.log(foo.name);
console.log(foo.bar.name);


В итоге должно получиться что то такое:
/sbin/tc qdisc del dev eth1 root
/sbin/tc qdisc add dev eth1 root handle 1 htb default 20 r2q 1
/sbin/tc qdisc del dev eth0 root
/sbin/tc qdisc add dev eth0 root handle 1 htb default 20 r2q 1
/sbin/tc qdisc del dev tun0 root
/sbin/tc qdisc add dev tun0 root handle 1 htb default 20 r2q 1
/sbin/tc class add dev eth1 parent 1: classid 1:2 htb rate 100Mbit
/sbin/tc class add dev eth1 parent 1:2 classid 1:10 htb rate 100Mbit
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.5 classid 1:10
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.6 classid 1:10
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.9 classid 1:10
/sbin/tc class add dev eth1 parent 1:2 classid 1:20 htb rate 2Mbit ceil 2Mbit
/sbin/tc class add dev eth1 parent 1:20 classid 1:21 htb rate 36Kbit ceil 0.5Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip sport 22 0xffff classid 1:21
/sbin/tc class add dev eth1 parent 1:20 classid 1:30 htb rate 1000Kbit ceil 2000Kbit prio 5
/sbin/tc qdisc add dev eth1 parent 1:30 handle 30 sfq perturb 10
/sbin/tc class add dev eth1 parent 1:30 classid 1:31 htb rate 100Kbit ceil 0.5Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.101 classid 1:31
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.100 classid 1:31
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.99 classid 1:31
/sbin/tc class add dev eth1 parent 1:30 classid 1:52 htb rate 100Kbit ceil 0.5Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.22 classid 1:52
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.27 classid 1:52
/sbin/tc class add dev eth1 parent 1:30 classid 1:60 htb rate 100Kbit ceil 1Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip dst 192.168.0.0/24 classid 1:60
/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 2Mbit ceil 2Mbit
/sbin/tc class add dev eth0 parent 1:2 classid 1:10 htb rate 128Kbit ceil 2Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dport 22 0xffff classid 1:10
/sbin/tc class add dev eth0 parent 1:2 classid 1:10 htb rate 512Kbit ceil 1Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dport 1194 0xffff classid 1:10
/sbin/tc class add dev eth0 parent 1:2 classid 1:20 htb rate 50Kbit ceil 2Mbit prio 5
/sbin/tc qdisc add dev eth0 parent 1:20 handle 20 sfq perturb 10
/sbin/tc class add dev tun0 parent 1: classid 1:2 htb rate 0.5Mbit ceil 1Mbit


Хочу заметить, что у меня несколько нетипичная ситуация, два интернет канала на 2 и 1 Mbit, и для каждого пользователя ограничение в 2 Mbit скорости загрузки, поэтому на графике видно, что если активен один пользователь — его скорость урезается на 2 Mbit, а если несколько — суммарная скорость может достигать и трех. На таком достаточно «тесном» канале работают более 20 человек, и вполне комфортно себя чувствуют, не мешая друг другу.
Эта картинка с реально действующего сервера, и она обновляется каждые 5 минут и отображает актуальную картину загрузки канала.


Foo.js
[http://habrahabr.ru/post/60095/ взято тут...]
 
module.exports = function () {
this.name = 'Foo';   
this.bar = new lib.a.c.Bar(); };
 
 
 
Bar.js
 
module.exports = function () { this.name = 'Bar'; };
 
 
 
LazyLoader.js
 
var fs = require('fs');
var path = require('path'); 
function getter(key, dir,file) {
  delete this[key];
  var fullPath = path.join(dir, file);
    try
{require.resolve(fullPath);}
    catch (e) {
                if
            (fs.existsSync(fullPath)) {
                  this[key] = new LazyLoader(path.join(dir, file));
                }       
    return this[key];
    }   
  this[key] = require(fullPath);   
    return this[key]; } 
function LazyLoader(dir) {
      var loader = this;
      if (!fs.existsSync(dir)) {
        return;
    }
  fs.readdirSync(dir).forEach(function(file) {
        var key = file.replace(/\.js$/, '');
        loader.__defineGetter__(key, getter.bind(loader, key, dir, file))
    }); } 
module.exports = LazyLoader; 
 
 
 
При запуске node index.js в консоли распечатается (как и ожидалось)
 
Foo Bar
 
 
 
В данном примере я использовал глобальную переменную lib. Если вы противник
глобальных переменных (или вы просто разрабатываете отдельный публичный модуль)
— то можно отказаться от глобальной переменной — в Foo.js придется написать,
например, так:
 
var path = require('path');
var LazyLoader = require('../../LazyLoader');
var lib = new LazyLoader(path.join(__dirname, '../../'));
module.exports = function() {
    this.name = 'Foo';
    this.bar = new lib.a.c.Bar();
};
 
 
И если у вас всего 1-2 подключаемых файла, то возможно данный подход покажется
вам неуместным, но при большем количестве — вы должны ощутить существенное
облегчение.
Кроме того вы можете сохранять ссылки на директории для сокрашения записи,
например:
 
var lib = new LazyLoader(__dirname);
var logLig = lib.dir1.dir2.dir3.log;
var f1 = new logLib.ConsoleLogger();
var f2 = new logLib.FileLogger(); // вместо //
var f1 = new lib.dir1.dir2.dir3.log.ConsoleLogger(); //
var f2 = new lib.dir1.dir2.dir3.log.FileLogger();  //  и вместо //
var f1 = new require(__dirname + '/dir1/dir2/dir3/log/ConsoleLogger)(); //
var f2 = new require(__dirname + '/dir1/dir2/dir3/log/FileLogger)();
 
 
 
 
'''Заключение'''
 
1. Указанный подход позволяет имитировать аналог '''namespace''' в других языках.
 
2. Приведенный в примере '''LazyLoader''' легко расширить для работы с несколькими
директориями, например, для смешвания или переопределения модулей:
 
var lib = new LazyLoader('globalLibDir', 'applicationSpecificLibDir');
 
 
 
3. Если Вы нашли неточности, опечатки или у вас есть альтернативные решения
подключения модулей — пишите в ЛС.
 
ссылка на оригинал статьи http://habrahabr.ru/post/164665/
 
[http://savepearlharbor.com/?p=164665 взято тут...]

Версия от 00:50, 7 июля 2014

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

Сформулируем, что же мы хотим получить в результате: 1. Чтобы канал поровну делился между пользователями. 2. Чтобы канал зря не простаивал. 3. Чтобы онлайн-игры, ssh и telnet не «лагали» даже при полной загрузке канала, например торрентами.


Если интернетом будут одновременно пользоваться 10 пользователей — каждый получит в свое распоряжение 1/10 часть канала, если в данный момент активен только один пользователь — он будет использовать весь канал сам. Добиться этого можно используя планировщик пакетов HTB, который входит в ядро linux начиная с версии 2.4.20. image Можно конфигурировать шейпер с помощью команды tc, но для более удобной и наглядной настройки я рекомендую скачать скрипт htb.init. Они использует для конфигурации htb набор конфигурационных файлов, именуемых так, что при сортировке по алфавиту их имена позволяют визуально представить себе дерево классов шейпера и удобно его редактировать. Предположим, что у нас на сервере есть интерфейс eth0, через который мы подключены к интернет, и eth1, который «смотрит» в локальную сеть.

Управлять можно только исходящим из интерфейса трафиком, поэтому для eth0 будут правила для upload трафика пользователей, а для — eth1 — download трафика.

По умолчанию конфигурационные файлы htb.init находятся в /etc/htb/. Для начала напишем правила шейпинга для upload трафика, они у нас будут простые. Создаем файл с именем eth0 (интерейс «смотрящий» в интернет), в него напищем следующие строки:

DEFAULT=20
R2Q=1

Параметр DEFAULT задает номер класса, к которому будет относиться трафик «по умолчанию» — обычно это класс с минимальным приоритетом. Параметр R2Q влияет на работу алгоритма разделения канала и зависит от ширины канала. Я подбирал его значение эмпирическим путем, для моего исходящего канала в 2 Mbit.

Далее, создадим файл eth0-2.full2MBit, для класса включающего в себя весь доступный интернет-канал. Имя файла состоит из имени интерфейса и id класса, после точки идет смысловое имя класса, используется как комментарий и системой игнорируется.

RATE=2Mbit
CEIL=2Mbit

RATE — это наша гарантированная полоса, CEIL — максимальная полоса. Так как у меня канал с гарантированной максимальной полосой в 2 Mbit, то эти параметры у меня равны.

Теперь мы создадим по одному файлу для каждого класса трафика, который у нас будет. Я у себя создал отдельные классы для ssh трафика, а так же трафика игр World Of Warcraft и Counter Strike, хотя вы можете сделать для всего высокоприоритетного трафика один класс.

Пример для ssh — создаем файл eth0-2:10.ssh. В имени файла через двоеточие указан id родительского класса 2 и id текущего класса — 10. Идентификаторы для класса вы можете выбирать произвольно.

# class for outgoing ssh
RATE=128Kbit
CEIL=2Mbit
RULE=*:22
PRIO=1
BURST=100Kb

В параметре RATE указана гарантированная полоса для этого класса, в CEIL — максимальная. Мы выделяем для ssh 128 KBit (как минимум) и разрешаем ему загрузить весь канал (я закачивать файлы по sftp). PRIO задает приоритет класса трафика (1- максимальный, чем больше число — тем меньш приоритет). BURST задает максимальный объем трафика, который будет передан на максимальной скорости перед тем, как перейти к передаче данных из дургих классов. Установив этот параметр в достаточно высокое значение мы добиваемся того, что трафик ssh будет передан с минимальными задержками. RULE задает правило, по которому будет отбираться трафик в этот класс. Формат — RULE=[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]] Обратите внимание на запятую! RULE=*:22 обозначает трафик, у которого порт назначения 22, а RULE=*:22, обозначает трафик, у которого исходящий порт — 22.

Создадим так же классы для других видов трафика, и класс для трафика «по умолчанию» с id 20 (мы указали вначале что именно в класс номер 20 надо направлять трафик «по умолчанию»). В нем укажем используемую дисциплину разделения канала LEAF=sfq, для того чтобы upload поровну делился между TCP сессиями разных пользователей.

Для eth1 правила будут почти такие же, только с учетом что общая ширина канала — 100 Mbit, мы ведь хотим чтобы можно было обращаться к локальным ресурсам сервера на полной скорости, для интернет-трафика выделен отдельный класс на 2 MBit, у которого как потомки добавлены классы отдельных пользователей, разделение по классам я делал по IP адресам. Для каждого пользователя можно указать максимальную и гарантированную скорость, а так же приоритет.

После правки конфигурации перезапускаем htb.init:

/etc/init.d/htb.init restart

И правила шейпинга трафика сразу же вступают в силу.

В процессе состевления правил обычно возникает необходимость как-то визуализировать трафик, в целях отладки и мониторинга, поэтому решил написать плагин для системы мониторинга серверов munin, который бы визуализировал распределение по классам HTB трафика. Выводить решил загрузку только классов-листьев дерева, так как именно они обычно несут смысловую нагрузку. Скачать плагин вы можете из официального репозитория плагинов munin, называется он qos_, просто скопируйте его в папку плагинов munin /usr/share/munin/plugins/ и в папке используемых плагинов /etc/munin/plugins сделайте на него символическую ссылку вида qos_eth1, где eth1 — имя интерфейса, на котором нужно мониторить загрузку. В файле конфигурации плагинов можно добавить следущее:

[qos_eth1]
env.ignore_queue1_10 yes
env.label_name1_31 Viperet
env.label_name1_32 Cornet

Параметр env.ignore_queue позволяет не отображать на графике состояние класса с указанным id, а параметр env.label_name — задать человекопонятную метку для класса на графике.

В итоге должно получиться что то такое:

/sbin/tc qdisc del dev eth1 root
/sbin/tc qdisc add dev eth1 root handle 1 htb default 20 r2q 1

/sbin/tc qdisc del dev eth0 root
/sbin/tc qdisc add dev eth0 root handle 1 htb default 20 r2q 1 

/sbin/tc qdisc del dev tun0 root
/sbin/tc qdisc add dev tun0 root handle 1 htb default 20 r2q 1

/sbin/tc class add dev eth1 parent 1: classid 1:2 htb rate 100Mbit

/sbin/tc class add dev eth1 parent 1:2 classid 1:10 htb rate 100Mbit
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.5 classid 1:10
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.6 classid 1:10
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.9 classid 1:10

/sbin/tc class add dev eth1 parent 1:2 classid 1:20 htb rate 2Mbit ceil 2Mbit

/sbin/tc class add dev eth1 parent 1:20 classid 1:21 htb rate 36Kbit ceil 0.5Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip sport 22 0xffff classid 1:21

/sbin/tc class add dev eth1 parent 1:20 classid 1:30 htb rate 1000Kbit ceil 2000Kbit prio 5
/sbin/tc qdisc add dev eth1 parent 1:30 handle 30 sfq perturb 10

/sbin/tc class add dev eth1 parent 1:30 classid 1:31 htb rate 100Kbit ceil 0.5Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.101 classid 1:31
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.100 classid 1:31
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.99 classid 1:31

/sbin/tc class add dev eth1 parent 1:30 classid 1:52 htb rate 100Kbit ceil 0.5Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.22 classid 1:52
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.0.27 classid 1:52

/sbin/tc class add dev eth1 parent 1:30 classid 1:60 htb rate 100Kbit ceil 1Mbit prio 5
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip dst 192.168.0.0/24 classid 1:60

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 2Mbit ceil 2Mbit

/sbin/tc class add dev eth0 parent 1:2 classid 1:10 htb rate 128Kbit ceil 2Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dport 22 0xffff classid 1:10

/sbin/tc class add dev eth0 parent 1:2 classid 1:10 htb rate 512Kbit ceil 1Mbit burst 100Kb prio 1
/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dport 1194 0xffff classid 1:10

/sbin/tc class add dev eth0 parent 1:2 classid 1:20 htb rate 50Kbit ceil 2Mbit prio 5
/sbin/tc qdisc add dev eth0 parent 1:20 handle 20 sfq perturb 10

/sbin/tc class add dev tun0 parent 1: classid 1:2 htb rate 0.5Mbit ceil 1Mbit

Хочу заметить, что у меня несколько нетипичная ситуация, два интернет канала на 2 и 1 Mbit, и для каждого пользователя ограничение в 2 Mbit скорости загрузки, поэтому на графике видно, что если активен один пользователь — его скорость урезается на 2 Mbit, а если несколько — суммарная скорость может достигать и трех. На таком достаточно «тесном» канале работают более 20 человек, и вполне комфортно себя чувствуют, не мешая друг другу. Эта картинка с реально действующего сервера, и она обновляется каждые 5 минут и отображает актуальную картину загрузки канала.

взято тут...