Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
HOWTO: Apache 2 bandwidth limiting
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
raoulduke
n00b
n00b


Joined: 26 Sep 2003
Posts: 58

PostPosted: Tue Sep 30, 2003 2:28 pm    Post subject: HOWTO: Apache 2 bandwidth limiting Reply with quote

This is a work-in-progress version on how to limit bandwidth for an Apache 2 webserver. For Apache version 1.3 I recommend using mod_throttle or mod_bandwidth. As these modules are not available for Apache 2, this guide will use the kernel built in packet scheduler. Don't worry, it's not as hard as it sounds.

What are we going to do? We will limit the outgoing total traffic from our Apache 2 webserver to the rest of the world.

So, if you have an internet connection with a low upload speed (e.g. 256 or 192 kbit/s) you will be able to cap your webserver-upload-speed to anything you want so that you can still comfortably browse the web or do other things on-line.

What are the steps to get it working?
- reconfigure the kernel to include QoS and traffic shaping
- emergeing a few small packages we will use
- design and implement a traffic shaping script
- make sure the script is started at boot time

Because we use a built-in kernel packet scheduler called 'htb' we have several advantages over a per-connection based limiter. The biggest advantage is that clients will always have an equal share of limited bandwidth: if there's one client, it gets the full-limited bandwidth. In the case of two clients, they both get half of the full-limited bandwidth.

Get ready because here we go, please buckle your seatbelts! Oh, and don't forget to su as you'll need root privileges for the largest part of this guide.

Step 1 - Kernel configuration
I hope you've got a file containing your current kernel configuration as this will make things a lot easier. Make sure that file is in the /usr/src/linux directory. We are going to start the menu setup of your kernel:
Code:

#cd /usr/src/linux
#make menuconfig

Now, load your configuration file using the option at the bottom of this menu:
Code:

Load an Alternate Configuration File

Make sure that the following option is enabled:
Code:

Code maturity level options  --->
   [*] Prompt for development and/or incomplete code/drivers

We are now going to enable all kernel options required for our basic, and future advanced traffic shaping, so let's go and enable these options. They must be compiled into the kernel, not as a module, hence the *:
Code:

*       QoS and/or fair queueing
        *       HTB packet scheduler
        *       QoS support
                *       Rate estimator
        *       Packet classifier API
                *       TC index classifier
                *       Routing table based classifier
                *       Firewall based classifier
                *       U32 classifier
        *       Traffic policing

Save this configuration, for instance as mykernel-htb. And compile your new kernel using:
Code:

#make dep ; make clean bzImage modules modules_install

Copy the kernel to your favourite location and add it to your bootloader, for instance:
Code:

#cp arch/i386/boot/bzImage /boot/kernel-htb
#vi /boot/grub/menu.lst

The kernel is ready. Reboot with the new -htb kernel.

Step 2 - emerging packages
There's not a lot we're going to need, just iproute, so type:
Code:

#emerge -p iproute
(check the output for anomalies)
#emerge iproute

Check that the package is fully working by issueing the 'tc' command as root:
Code:

#tc

Your output should look like something like this:
Code:

Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }
where  OBJECT := { qdisc | class | filter }
       OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -b[atch] file }

This is good as it means 'tc' is working. Now let's head over to our script creation!

Step 3 - Designing and implementing our script
FIXME: explain what is happening here

For now, just assume I'm right. We're going to build a htb tree with only two leaves and one parent node. One leaf is going to be the traffic limiting node, the other is the rest of the unshaped traffic. You must now decide what upload speed you want Apache to have in kilobytes per second. The tree we will build looks like this:
Code:

       NIC
      (eth)
        |
        |
        |
        |
       LINK
      X kbps
        /\
       /  \
      /    \
     /      \
    /        \
 HTTP       REST
Y kbps    X-Y kbps

Now you must think up the following data:
- the ethernet device, I will use eth0
- the linkspeed, I will use 1024kpbs
- the Apache upload speed, I will use 20kbps (this is 160 kbit/s)

Let's call the ethernet device EDEV, the linkspeed LSPD and the Apache upload speed ASPD. We will have to create the following script using our favourite editor (as long as it's vi(m)):
Code:

#!/bin/bash
# change these values to suit your needs
EDEV="eth0"
LSPD="1024kbps"
ASPD="20kbps"

# create root node
tc qdisc add dev $EDEV root handle 1: htb default 11

# create LINK class
tc class add dev $EDEV parent 1: classid 1:1 htb rate $LSPD

# create our HTTP shaping class
tc class add dev $EDEV parent 1:1 classid 1:10 htb rate $ASPD

# create our REST class for unutilized bandwidth
tc class add dev $EDEV parent 1:1 classid 1:11 htb rate $LSPD

# create the filter for the HTTP class, we filter on source port 80 (http)
tc filter add dev $EDEV protocol ip parent 1:0 prio 1 u32 match ip sport 80 0xffff flowid 1:10

Save this script somewhere you can remember, for instance /etc/htb-script.sh.

Step 4 - making the script startup at boot
We must now create a script to stop our traffic shaping activities, so create a file with your editor containing:
Code:

#!/bin/bash
EDEV="eth0"

tc qdisc del dev $EDEV root

Save the file, for instance as /etc/htb-stop.sh.

We must make sure we can execute our scripts later on, so chmod them:
Code:

#chmod +x /etc/htb-script.sh
#chmod +x /etc/htb-stop.sh


We will now create a script that is going to be placed in /etc/init.d, so fire up your editor again and create this:
Code:

#!/sbin/runscript

depend() {
        use logger
        need net
}

start() {
        ebegin "Starting htb"
        /etc/htb-script.sh
        eend $?
}

stop() {
        ebegin "Stopping htb"
        /etc/htb-stop.sh
        eend $?
}

Save the script as /etc/init.d/htb. And chmod it as well:
Code:

#chmod +x /etc/init.d/htb

We want to run this script at boot time, so we will add it to the default runlevel using:
Code:

#rc-update add htb default

Everything is now in place. To start our script without rebooting type:
Code:

#/etc/init.d/htb start

That should do it!

Questions / comments
Help with the FIXME's is appreciated. They will disappear within the next few days / weeks.

I wish you luck!
Back to top
View user's profile Send private message
benca1
Tux's lil' helper
Tux's lil' helper


Joined: 28 Mar 2003
Posts: 76

PostPosted: Thu Jan 29, 2004 5:08 pm    Post subject: Reply with quote

Can't wait to try this. Thanks an awful lot of writing this.
Back to top
View user's profile Send private message
apyh
n00b
n00b


Joined: 17 Mar 2003
Posts: 67
Location: Texas

PostPosted: Fri Feb 13, 2004 11:45 pm    Post subject: this looks great Reply with quote

could i get a bit more explanation of how that last tc command works?

Code:

# create the filter for the HTTP class, we filter on source port 80 (http)
tc filter add dev $EDEV protocol ip parent 1:0 prio 1 u32 match ip sport 80 0xffff flowid 1:10


I've got several ideas in mind, for one, adding more branches to this tree, one for http (restricted), bittorrent (restricted), and the rest (unrestricted).

However, for bt, i'll need to restrict based on a range of ports. So a better explanation of the last command would be great.

From the man page, i get the general syntax, but i'm thrown off between the arguments you use between priority and flow:

Code:

u32 match ip sport 80 0xffff


u32 is the filtertype, but where do i find documentation on the rest of the arguments for this filter (like sport and that mask)?

On a side note, why is the parent node referenced as 1:0 instead of just 1: which was used in the root creation in the first tc command?
Back to top
View user's profile Send private message
sn4ip3r
Guru
Guru


Joined: 14 Dec 2002
Posts: 325
Location: Tallinn, Estonia

PostPosted: Sat Feb 14, 2004 10:05 am    Post subject: Reply with quote

When I needed to limit the bandwidth apache2 used I wrote a version of 'cat' which took as a parameter the needed bandwidth and then used mod_filter_ext to pipe all traffic through the program.

Something like this:

Code:

ExtFilterDefine ksec16 mode=output cmd="/usr/local/bin/throttle_cat 16384" preservescontentlength
<Location /~sn4ip3r/packages>
    # 16KB/s
    SetOutputFilter ksec16
</Location>
Back to top
View user's profile Send private message
sn4ip3r
Guru
Guru


Joined: 14 Dec 2002
Posts: 325
Location: Tallinn, Estonia

PostPosted: Sat Apr 10, 2004 7:54 pm    Post subject: Reply with quote

I described another method of limiting apache bandwidth in my previous reply to this post, an accurate name would be "Poor mans apache2 bandwidth limiting":P.

Here is a little bit more accurate howto for that.

1. Download a customized version of cat (writte by me) from here.

2. Compile it
Code:

g++ throttle_cat.cpp -o throttle_cat

(although the program is called cat, it is not a full implementation, it only relays data sent to its standard input and it does not accept any other parameters besides data rate which btw. is bytes per second, so to test it you could "cat filename|throttle_cat 10" to see data flow 10 bytes at a time with intervals of 1 second)

3. Put it in a safe place where you keep your binaries which are not installed by portage (or make an ebuild if you really want to)

4. Edit /etc/apache2/conf/commonapache.conf
Code:

# Following is an example, customize it to your needs

# define a 16KB/s filter
ExtFilterDefine ksec16 mode=output cmd="/usr/local/bin/throttle_cat 16384" preservescontentlength

# apply the filter to /~sn4ip3r/packages
<Location /~sn4ip3r/packages>
       # 16KB/s
      SetOutputFilter ksec16
</Location>


And thats it. One thing you should know, this method creates a per-client limit, not a per-location or overall limit, so if you need an overall limit you have to limit the number of connections allowed.

Hope this is of use to someone

[edit] updated URL


Last edited by sn4ip3r on Fri Jul 08, 2005 9:56 am; edited 1 time in total
Back to top
View user's profile Send private message
MooktaKiNG
Guru
Guru


Joined: 11 Nov 2002
Posts: 326
Location: London, UK

PostPosted: Sun Apr 11, 2004 2:50 pm    Post subject: Reply with quote

is it possible to give different limits on different interfaces.

For example my server connects to the internet through eth0, and NAT is eth1. I want full speed, unlimited, on eth1. but i want to limit speed for eth0.

Is this possible?
_________________
http://www.mooktakim.com
Athlon XP 2001, Giga-Byte GA-7VRXP MB, 640Mb DDR RAM 333MHz, MSI Geforce 4800SE 128Mb DDR, 40x12x48 Liteon CDRW drive, Flower Cooler, ADSL Router
Back to top
View user's profile Send private message
Lajasha
Veteran
Veteran


Joined: 17 Mar 2004
Posts: 1040
Location: Vibe Central

PostPosted: Sat Jun 26, 2004 5:08 pm    Post subject: Re: HOWTO: Apache 2 bandwidth limiting Reply with quote

raoulduke wrote:
Step 2 - emerging packages
There's not a lot we're going to need, just iproute, so type:
Code:

#emerge -p iproute
(check the output for anomalies)
#emerge iproute


Just thought I would let ya know this should be updated to:
Code:
emerge -p iproute2

_________________
Come and play in my land
Back to top
View user's profile Send private message
jevidl
Tux's lil' helper
Tux's lil' helper


Joined: 22 Jul 2004
Posts: 111
Location: Ann Arbor, MI

PostPosted: Thu Jul 22, 2004 5:51 am    Post subject: Reply with quote

Excellent guide!

Thanks so much for posting the information, for those of us with a bandwidth capped cable modem it's a lifesaver. Now I can share files with friends and not have to worry about not being able to surf or closing out the rest of the people in the house. Thanks again!
Back to top
View user's profile Send private message
jkolb
n00b
n00b


Joined: 07 Jan 2004
Posts: 3

PostPosted: Thu Jul 22, 2004 3:14 pm    Post subject: Reply with quote

Try using tcc (sys-apps/tcng) to generate a tc script. I found it much easier to define my ruleset using their syntax, and let it generate the ugliness that tc understands.

You can find more information on tcng at http://tcng.sf.net/

Hm. There seems to be a newer version of tcng that's not in portage. Anyone up for updating the ebuild?
Back to top
View user's profile Send private message
roko
n00b
n00b


Joined: 28 Feb 2003
Posts: 26
Location: Slovenjia

PostPosted: Wed Aug 18, 2004 11:03 am    Post subject: Reply with quote

Great HOWTO. Thanks.
Back to top
View user's profile Send private message
lisa
Retired Dev
Retired Dev


Joined: 01 Jun 2003
Posts: 273
Location: York, UK again! Horray!

PostPosted: Sat Sep 04, 2004 9:18 pm    Post subject: Reply with quote

This may help :)

Code:

#!/sbin/runscript
# /etc/init.d/rate_limit_apache
depend() {
        use logger
        need net
}

start() {
        ebegin "Starting Apache Rate Limit on ${EDEV}"
        # create root node
        ${TC} qdisc add dev $EDEV root handle 1: htb default 11

        # create LINK class
        ${TC} class add dev $EDEV parent 1: classid 1:1 htb rate $LSPD

        # create our HTTP shaping class
        ${TC} class add dev $EDEV parent 1:1 classid 1:10 htb rate $ASPD

        # create our REST class for unutilized bandwidth
        ${TC} class add dev $EDEV parent 1:1 classid 1:11 htb rate $LSPD

        # create the filter for the HTTP class, we filter on source port 80 (http)
        ${TC} filter add dev $EDEV protocol ip parent 1:0 prio 1 u32 match ip sport 80 0xffff flowid 1:10
        eend $?
}

stop() {
        ebegin "Stopping Apache Rate Limit on ${EDEV}"
        tc qdisc del dev $EDEV root
        eend $?
}


Code:

#/etc/conf.d/rate_limit_apache
EDEV="eth1"
LSPD="3084kbps"
ASPD="10kbps"
TC="/sbin/tc"

_________________
Distcc guide
Visit my website
I maintain Distcc, Ccache, Memcached, and some others (i think)
Back to top
View user's profile Send private message
Raniz
l33t
l33t


Joined: 13 Sep 2003
Posts: 965
Location: Lund, Sweden

PostPosted: Fri Sep 24, 2004 11:33 pm    Post subject: Reply with quote

Is it possible to create a limit for multiple ports?

I want to have a limit of 250kbps spanning over three or four ports. So if I upload at 100kbps on one port, there's 150 left for the other two. Or if I upload at 25kbps on one port, 75 kbps on one port and 35 kbps on the third, there's 115kbps left for the fourth port. Get the idea?
_________________
#312470 @ http://counter.li.org/
Back to top
View user's profile Send private message
electrofreak
l33t
l33t


Joined: 30 Jun 2004
Posts: 713
Location: Ohio, USA

PostPosted: Thu Aug 18, 2005 5:04 am    Post subject: Reply with quote

Is it possible to make it not throttle the bandwidth within the network?

Like, when browsing from outside our network (from that world out there!) it would limit the speed, but when from 192.168.0.1-255 it wouldn't limit the speed at all.

Edit: didn't realize how old this topic was. Is this bandwidth limiting stuff still valid? Is it built into apache2 now?
_________________
Desktop: ABit AN8, Athlon64 X2 4400+ 939 2.75GHz, 2x1GB Corsair XMS DDR400, 2x160GB SATA RAID-0, 2x20"W, Vista Ultimate x64
Laptop: 15.4" MacBook Pro 2.4Ghz, 2x1GB RAM, 160GB, Mac OS X 10.5.1
Server: PIII 550Mhz, 3x128MB RAM, 160GB, Ubuntu Server 7.10
Back to top
View user's profile Send private message
ARealNoobOne
n00b
n00b


Joined: 13 Feb 2005
Posts: 59

PostPosted: Fri Aug 19, 2005 4:38 am    Post subject: Re: HOWTO: Apache 2 bandwidth limiting Reply with quote

raoulduke wrote:
We are now going to enable all kernel options required for our basic, and future advanced traffic shaping, so let's go and enable these options. They must be compiled into the kernel, not as a module, hence the *:
Code:

*       QoS and/or fair queueing
        *       HTB packet scheduler
        *       QoS support
                *       Rate estimator
        *       Packet classifier API
                *       TC index classifier
                *       Routing table based classifier
                *       Firewall based classifier
                *       U32 classifier
        *       Traffic policing



Excellent guide.

Could you please explain why traffic shaping options must be builtin rather than modular ("they _must_ be compiled into the kernel") ? I hate having builtin modules that are not critical to boot.
Back to top
View user's profile Send private message
meulie
l33t
l33t


Joined: 17 Jun 2003
Posts: 845
Location: a Dutchman living in Norway

PostPosted: Mon Sep 19, 2005 12:17 pm    Post subject: Reply with quote

Is there also a way to limit the amount of bandwidth consumed per external IP per day?
_________________
Greetz,
Evert Meulie
Back to top
View user's profile Send private message
dembol
n00b
n00b


Joined: 09 Oct 2005
Posts: 1
Location: Gdynia

PostPosted: Sun Oct 09, 2005 8:51 am    Post subject: Reply with quote

Hi

raoulduke:
Quote:
For Apache version 1.3 I recommend using mod_throttle or mod_bandwidth. As these modules are not available for Apache 2


meulie:
Quote:
Is there also a way to limit the amount of bandwidth consumed per external IP per day?


There is mod_cband for the Apache2 server.

Main features:
- per-user bandwidth limiting
- per-virtualhost bandwidth limiting
- per-destination class bandwidth limiting
- status handler (like in mod_throttle)

homepage of the project: http://cband.linux.pl
the cband-status handler demo: http://dembol.nasa.pl/cband-status, (in XML -> http://dembol.nasa.pl/cband-status?xml)

But, it isn't in the gentoo portage yet :cry: You can download the mod_cband sources (http://cband.linux.pl/download/mod_cband-0.9.5.tgz) and compile it for your Apache

Best regards
Back to top
View user's profile Send private message
electrofreak
l33t
l33t


Joined: 30 Jun 2004
Posts: 713
Location: Ohio, USA

PostPosted: Thu Oct 13, 2005 2:15 am    Post subject: Reply with quote

Hm. Looks good. Thanks.
_________________
Desktop: ABit AN8, Athlon64 X2 4400+ 939 2.75GHz, 2x1GB Corsair XMS DDR400, 2x160GB SATA RAID-0, 2x20"W, Vista Ultimate x64
Laptop: 15.4" MacBook Pro 2.4Ghz, 2x1GB RAM, 160GB, Mac OS X 10.5.1
Server: PIII 550Mhz, 3x128MB RAM, 160GB, Ubuntu Server 7.10
Back to top
View user's profile Send private message
Sakkath
Apprentice
Apprentice


Joined: 06 Nov 2005
Posts: 198
Location: Pawtucket, RI

PostPosted: Tue Feb 13, 2007 1:38 pm    Post subject: Reply with quote

mod_cband is now in portage, it's masked for ~amd64 though :(.
_________________
The person who makes no mistakes does not usually make anything.

Please add [SOLVED] to the subject of your original post when you feel that your problem is resolved.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum