使用谷歌的BBR拥塞算法为TCP加速

BBR简述

Google 开源了其 TCP BBR 拥塞控制算法,并提交到了 Linux 内核,从 4.9 开始,Linux 内核已经用上了该算法。 BBR 算法的目的是要尽量跑满带宽,并且尽量不要有排队的情况。它可以起到单边加速 TCP 连接的效果。

TCP BBR 致力于解决两个问题

  • 在有一定丢包率的网络链路上充分利用带宽
  • 降低网络链路上的 buffer 占用率,从而降低延迟

BBR算法的优势

一键配置脚本

该脚本用于 CentOS 系列 6 和 7 版本的系统,执行后将升级内核并且通过 yum 安装,可能下载较慢,可手动下载 rpm 包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/usr/bin/env bash
:<<:
------------------------------------------------
FileName : google_bbr_centos.sh
Author : Silence
Create Time : 2017-05-09 15:09:16
Last modified : 2017-11-26 17:56:25
Mail :
Version : 0.0.1
Description : Auto install latest kernel for TCP BBR
CopyRight :
------------------------------------------------
:

# Set up a default search path.
PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin"
export PATH

# Make sure umask is sane
umask 022

# terminal sequence to set color to a 'success' color (currently: green)
SETCOLOR_SUCCESS="echo -en \\033[0;32m"
# terminal sequence to set color to a 'failure' color (currently: red)
SETCOLOR_FAILURE="echo -en \\033[0;31m"
# terminal sequence to set color to a 'warning' color (currently: yellow)
SETCOLOR_WARNING="echo -en \\033[0;33m"
# terminal sequence to reset to the default color.
SETCOLOR_NORMAL="echo -en \\033[0;39m"

# Log that something succeeded
echo_info(){
echo -en "[ ";
${SETCOLOR_SUCCESS};
echo -en " Info ";
${SETCOLOR_NORMAL};
echo -en " ] ";
echo "$@"
}
# Log that something Error
echo_error(){
echo -en "[ ";
${SETCOLOR_FAILURE};
echo -en " Error ";
${SETCOLOR_NORMAL};
echo -en " ] ";
echo "$@"
}
# Log a warning
echo_warning(){
echo -en "[ ";
${SETCOLOR_WARNING};
echo -en " Warning ";
${SETCOLOR_NORMAL};
echo -en " ] ";
echo "$@"
}

bbr_sysctl_config(){
sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf
sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf
echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf
sysctl -p >/dev/null 2>&1
}

get_os() {
[ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return
[ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
[ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
}

get_char() {
SAVEDSTTY=`stty -g`
stty -echo
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}

clear
echo "------------- System Information --------------"
echo
echo " OS : $(get_os)"
echo " Arch : $(uname -m) $(getconf LONG_BIT) Bit"
echo " Kernel : $(uname -r)"
echo
echo "-----------------------------------------------"
echo " Auto upgrade latest kernel and turn on TCP BBR"
echo "-----------------------------------------------"
echo
echo "Press any key to start...or Press Ctrl+C to cancel"
char=$(get_char)
echo


#------------------------------------------------
# Test the operator is root or not
#------------------------------------------------
if test "${EUID}" -ne 0 -o "${USER}" != "root";then
echo_error "Only root can run this script ... "
exit 5
else
echo_info "Operator is root "
fi
#************************************************


#------------------------------------------------
# Check network is rechable or not
#------------------------------------------------
dstname="www.baidu.com"
if (ping ${dstname} -c 3 -i 0.01 -w 2 -q 1>/dev/null 2>&1)then
echo_info "Network is rechable "
else
RETVAL=$?
echo_error "Network is unreachable , please check "
exit 5
fi
#************************************************


#------------------------------------------------
# Check your OS is Redhat release or not
#------------------------------------------------
rla="$(egrep -i "centos|red hat|redhat" /etc/issue)"
rlb="$(egrep -i "centos|red hat|redhat" /proc/version)"
if [ -f /etc/centos-release -o -n "${rla}" -o -n "${rlb}" ]; then
echo_info "OS is Redhat release"
else
echo_error "Only support for CentOS"
exit 5
fi
#************************************************


#------------------------------------------------
# Check bbr status
#------------------------------------------------
conGestion="$(set -- $(sysctl -n net.ipv4.tcp_available_congestion_control);echo $1)"
# Get the congestion_control from Kernel parameter
bbrmodules="$(lsmod | fgrep tcp_bbr)"
# Show the status of tcp_bbr module in the Linux Kernel
if [ "${conGestion}" = "bbr" -a -n "${bbrmodules}" ];then
echo_info "TCP BBR has been installed. Nothing to do..."
exit 5
fi
#************************************************


#------------------------------------------------
# Check version of kernel is newer or not
#------------------------------------------------
kernelRelease="$(uname -r)"
newORold=$(set -- ${kernelRelease%%-*} 4.9;test "$(echo -e "$1\n$2" | sort -rV | head -1)" == "$1" && echo newer || echo older )
if test "${newORold}" == 'newer';then
echo_info "Version of your kernel is greater than 4.9 , directly setting TCP BBR..."
bbr_sysctl_config
echo_info "Setting TCP BBR ..."
echo_info 'Complete ! '
exit 5
fi
#************************************************


#------------------------------------------------
# Install elrepo
#------------------------------------------------
OS_X="`grep -Po '(?<=\brelease )[\d]' /etc/redhat-release`"
if test ! -z "${OS_X//[0-9]/}";then
echo_error "Not available for your system :("
else
echo_info "Installing elrepo"
fi

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
case $OS_X in
6)
rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm
;;
7)
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
;;
*)
echo_error "Not support for CentOS${OS_X}"
exit 5
;;
esac

if [ ! -s /etc/yum.repos.d/elrepo.repo ]; then
echo_error "Install elrepo failed , please check "
exit 5
fi
#************************************************


#------------------------------------------------
# Upgrade kernel
#------------------------------------------------
yum --enablerepo=elrepo-kernel -y install kernel-ml kernel-ml-devel

echo_info "Query package :"
echo '------------------------------------------------'
rpm -qa kernel-ml
echo '------------------------------------------------'
echo
if [ $? -ne 0 ]; then
echo_error "Install latest kernel failed, please check it."
exit 5
fi
#************************************************


#------------------------------------------------
# config for grub
#------------------------------------------------
case $OS_X in
6)
if [ ! -s "/boot/grub/grub.conf" ]; then
echo_error "/boot/grub/grub.conf wrong, please check it."
exit 5
fi

echo_info "List of kernel that is available"
echo '------------------------------------------------'
awk '/title/{$1="";print}' /etc/grub.conf
echo '------------------------------------------------'
echo

sed -ri 's/^default=.*/default=0/g' /boot/grub/grub.conf
;;
7)
if [ ! -s "/boot/grub2/grub.cfg" ]; then
echo_error "/boot/grub2/grub.cfg wrong, please check it."
exit 5
fi

echo_info "List of kernel that is available"
echo '------------------------------------------------'
awk -F'[\047]+' '/^menuentry/{print $2}' /boot/grub2/grub.cfg
echo '------------------------------------------------'
echo

grub_default_kernel=$(awk -F'[\047]+' '/^menuentry/{print "\047"$2"\047";exit}' /boot/grub2/grub.cfg)

echo "grub2-set-default 0"
echo
grub2-set-default 0

echo "grub2-mkconfig -o /boot/grub2/grub.cfg"
echo
grub2-mkconfig -o /boot/grub2/grub.cfg
;;
*)
echo_error "Not support for CentOS${OS_X}"
exit 5
;;
esac
#************************************************

bbr_sysctl_config

#------------------------------------------------
# Waitting for reboot
#------------------------------------------------
echo
echo_warning "The system needs to reboot."
echo
read -p 'Do you want to restart system ? [yes/no] ' yesOrno
case "${yesOrno}" in
y|Y|[yY][eE]|[yY][eE][sS])
reboot
echo "Reboot test"
;;
n|N|[nN][oO])
echo_info "Reboot has been canceled..."
exit 5
;;
esac
#************************************************

参考命令

查看内核模块的信息

1
modinfo tcp_bbr

查看可用内核

1
awk -F'[\047]+'  '/^menuentry/{print $2}' /boot/grub2/grub.cfg

查看当前内核的版本

1
uname -r

修改开机时默认使用的内核

1
2
3
grub2-set-default 'CentOS Linux (4.14.2-1.el7.elrepo.x86_64) 7 (Core)'
# 或使用索引号0、1、2.....
grub2-set-default 0

查看内核修改结果

1
grub2-editenv list

重新生成 grub2 的配置文件

1
grub2-mkconfig -o /boot/grub2/grub.cfg

GRUB 2 操作帮助: http://fedoraproject.org/wiki/GRUB_2/zh-cn

有钱任性,请我吃包辣条
0%