Currently nginx uses all my bandwidth. How do I leave some for rsync?
This is a sketch and you need to figure out all the details yourself, but this is how it should be possible:
What you want can be accomplished by using two Linux specific kernel facilities, namely
cgroups and the
QoS subsystem with it's scheduling policies.
What you basically need to is to put nginx and it's children into an own cgroup, use the
discq scheduler from QoS which then can act on the
net_cls controller (See this RedHat document that roughly describes net_cls). What it does is to append a tag to each packet that originates from a socket that was created by a PID coming from the cgroup where nginx sits.
You of course need to create the same cgroup setup for rsync. Take care that you can do all the cgroups machinery before you call rsync or setup rsyncd accordingly.
This 'tag' that is being attached from net_cls then can be used as classid in the filter attached to qdisc to pass the traffic to different classes. You also need to define bandwidth classes that contain the bandwith limits you want to assign to your two cgroups say 500Mbit/s ceiling for nginx and 500Mbit/s for rsync. Please note that the usual caveats about QoS and rate limiting or queuing TCP apply.
This code would rate limit port 80,443 (HTTP,HTTPS) to a maximum of 0.5Mb and burst to 0.6Mb. Tweak/adjust to suit your requirements.
/sbin/tc qdisc add dev eth0 root handle 1: htb /sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 1024kbps /sbin/tc class add dev eth0 parent 1:1 classid 1:5 htb rate 512kbps ceil 640kbps prio 1 /sbin/tc class add dev eth0 parent 1:1 classid 1:6 htb rate 512kbps ceil 640kbps prio 0 /sbin/tc filter add dev eth0 parent 1:0 prio 1 protocol ip handle 5 fw flowid 1:5 /sbin/tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:6 /sbin/iptables -A OUTPUT -t mangle -p tcp --sport 80 -j MARK --set-mark 5 /sbin/iptables -A OUTPUT -t mangle -p tcp --sport 443 -j MARK --set-mark 6