谷歌BBR拥塞算法内核更新
程序员文章站
2022-08-28 12:22:38
为什么想到这个呢,算法什么的又不太懂,这是 因为搭建VPN + BBR 与之简直绝配 有的人搭建SSR ,配一个什么锐速,还需要降内核版本, 而且还容易出错,降了之后更加容易出现兼容性问题,所以偶尔看到了google的BBR 拥塞阻塞算法 算法原理不知道,也不想去深究 。 原理 这篇博客 讲得还是很 ......
为什么想到这个呢,算法什么的又不太懂,这是 因为搭建vpn + bbr 与之简直绝配
有的人搭建ssr ,配一个什么锐速,还需要降内核版本, 而且还容易出错,降了之后更加容易出现兼容性问题,所以偶尔看到了google的bbr 拥塞阻塞算法
算法原理不知道,也不想去深究 。 原理 讲得还是很清楚的 ,可以一探
google 开源了其 tcp bbr 拥塞控制算法,并提交到了 linux 内核,从 4.9 开始,linux 内核已经用上了该算法。根据谷歌的风格,google 总是先在自家的生产环境上线运用后,才会将代码开源,此次也不例外。
根据大佬的实地测试,在部署了最新版内核并开启了 tcp bbr 的机器上,网速甚至可以提升好几个数量级。
根据某个大佬开发的一键安装的脚本,可以实现最新内核的安装和 tcp bbr 脚本
脚本如下:
1 #!/usr/bin/env bash 2 # 3 # auto install latest kernel for tcp bbr 4 # 5 # system required: centos 6+, debian7+, ubuntu12+ 6 # 7 # copyright (c) 2016-2018 teddysun <i@teddysun.com> 8 # 9 # url: https://teddysun.com/489.html 10 # 11 12 red='\033[0;31m' 13 green='\033[0;32m' 14 yellow='\033[0;33m' 15 plain='\033[0m' 16 17 cur_dir=$(pwd) 18 19 [[ $euid -ne 0 ]] && echo -e "${red}error:${plain} this script must be run as root!" && exit 1 20 21 [[ -d "/proc/vz" ]] && echo -e "${red}error:${plain} your vps is based on openvz, which is not supported." && exit 1 22 23 if [ -f /etc/redhat-release ]; then 24 release="centos" 25 elif cat /etc/issue | grep -eqi "debian"; then 26 release="debian" 27 elif cat /etc/issue | grep -eqi "ubuntu"; then 28 release="ubuntu" 29 elif cat /etc/issue | grep -eqi "centos|red hat|redhat"; then 30 release="centos" 31 elif cat /proc/version | grep -eqi "debian"; then 32 release="debian" 33 elif cat /proc/version | grep -eqi "ubuntu"; then 34 release="ubuntu" 35 elif cat /proc/version | grep -eqi "centos|red hat|redhat"; then 36 release="centos" 37 else 38 release="" 39 fi 40 41 is_digit(){ 42 local input=${1} 43 if [[ "$input" =~ ^[0-9]+$ ]]; then 44 return 0 45 else 46 return 1 47 fi 48 } 49 50 is_64bit(){ 51 if [ $(getconf word_bit) = '32' ] && [ $(getconf long_bit) = '64' ]; then 52 return 0 53 else 54 return 1 55 fi 56 } 57 58 get_valid_valname(){ 59 local val=${1} 60 local new_val=$(eval echo $val | sed 's/[-.]/_/g') 61 echo ${new_val} 62 } 63 64 get_hint(){ 65 local val=${1} 66 local new_val=$(get_valid_valname $val) 67 eval echo "\$hint_${new_val}" 68 } 69 70 #display memu 71 display_menu(){ 72 local soft=${1} 73 local default=${2} 74 eval local arr=(\${${soft}_arr[@]}) 75 local default_prompt 76 if [[ "$default" != "" ]]; then 77 if [[ "$default" == "last" ]]; then 78 default=${#arr[@]} 79 fi 80 default_prompt="(default ${arr[$default-1]})" 81 fi 82 local pick 83 local hint 84 local vname 85 local prompt="which ${soft} you'd select ${default_prompt}: " 86 87 while : 88 do 89 echo -e "\n------------ ${soft} setting ------------\n" 90 for ((i=1;i<=${#arr[@]};i++ )); do 91 vname="$(get_valid_valname ${arr[$i-1]})" 92 hint="$(get_hint $vname)" 93 [[ "$hint" == "" ]] && hint="${arr[$i-1]}" 94 echo -e "${green}${i}${plain}) $hint" 95 done 96 echo 97 read -p "${prompt}" pick 98 if [[ "$pick" == "" && "$default" != "" ]]; then 99 pick=${default} 100 break 101 fi 102 103 if ! is_digit "$pick"; then 104 prompt="input error, please input a number" 105 continue 106 fi 107 108 if [[ "$pick" -lt 1 || "$pick" -gt ${#arr[@]} ]]; then 109 prompt="input error, please input a number between 1 and ${#arr[@]}: " 110 continue 111 fi 112 113 break 114 done 115 116 eval ${soft}=${arr[$pick-1]} 117 vname="$(get_valid_valname ${arr[$pick-1]})" 118 hint="$(get_hint $vname)" 119 [[ "$hint" == "" ]] && hint="${arr[$pick-1]}" 120 echo -e "\nyour selection: $hint\n" 121 } 122 123 version_ge(){ 124 test "$(echo "$@" | tr " " "\n" | sort -rv | head -n 1)" == "$1" 125 } 126 127 get_latest_version() { 128 latest_version=($(wget -qo- https://kernel.ubuntu.com/~kernel-ppa/mainline/ | awk -f'\"v' '/v[4-9]./{print $2}' | cut -d/ -f1 | grep -v - | sort -v)) 129 130 [ ${#latest_version[@]} -eq 0 ] && echo -e "${red}error:${plain} get latest kernel version failed." && exit 1 131 132 kernel_arr=() 133 for i in ${latest_version[@]}; do 134 if version_ge $i 4.14; then 135 kernel_arr+=($i); 136 fi 137 done 138 139 display_menu kernel last 140 141 if [[ `getconf word_bit` == "32" && `getconf long_bit` == "64" ]]; then 142 deb_name=$(wget -qo- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-image" | grep "generic" | awk -f'\">' '/amd64.deb/{print $2}' | cut -d'<' -f1 | head -1) 143 deb_kernel_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${deb_name}" 144 deb_kernel_name="linux-image-${kernel}-amd64.deb" 145 modules_deb_name=$(wget -qo- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-modules" | grep "generic" | awk -f'\">' '/amd64.deb/{print $2}' | cut -d'<' -f1 | head -1) 146 deb_kernel_modules_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${modules_deb_name}" 147 deb_kernel_modules_name="linux-modules-${kernel}-amd64.deb" 148 else 149 deb_name=$(wget -qo- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-image" | grep "generic" | awk -f'\">' '/i386.deb/{print $2}' | cut -d'<' -f1 | head -1) 150 deb_kernel_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${deb_name}" 151 deb_kernel_name="linux-image-${kernel}-i386.deb" 152 modules_deb_name=$(wget -qo- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-modules" | grep "generic" | awk -f'\">' '/i386.deb/{print $2}' | cut -d'<' -f1 | head -1) 153 deb_kernel_modules_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${modules_deb_name}" 154 deb_kernel_modules_name="linux-modules-${kernel}-i386.deb" 155 fi 156 157 [ -z ${deb_name} ] && echo -e "${red}error:${plain} getting linux kernel binary package name failed, maybe kernel build failed. please choose other one and try again." && exit 1 158 } 159 160 get_opsy() { 161 [ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return 162 [ -f /etc/os-release ] && awk -f'[= "]' '/pretty_name/{print $3,$4,$5}' /etc/os-release && return 163 [ -f /etc/lsb-release ] && awk -f'[="]+' '/description/{print $2}' /etc/lsb-release && return 164 } 165 166 opsy=$( get_opsy ) 167 arch=$( uname -m ) 168 lbit=$( getconf long_bit ) 169 kern=$( uname -r ) 170 171 get_char() { 172 savedstty=`stty -g` 173 stty -echo 174 stty cbreak 175 dd if=/dev/tty bs=1 count=1 2> /dev/null 176 stty -raw 177 stty echo 178 stty $savedstty 179 } 180 181 getversion() { 182 if [[ -s /etc/redhat-release ]]; then 183 grep -oe "[0-9.]+" /etc/redhat-release 184 else 185 grep -oe "[0-9.]+" /etc/issue 186 fi 187 } 188 189 centosversion() { 190 if [ x"${release}" == x"centos" ]; then 191 local code=$1 192 local version="$(getversion)" 193 local main_ver=${version%%.*} 194 if [ "$main_ver" == "$code" ]; then 195 return 0 196 else 197 return 1 198 fi 199 else 200 return 1 201 fi 202 } 203 204 check_bbr_status() { 205 local param=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}') 206 if [[ x"${param}" == x"bbr" ]]; then 207 return 0 208 else 209 return 1 210 fi 211 } 212 213 check_kernel_version() { 214 local kernel_version=$(uname -r | cut -d- -f1) 215 if version_ge ${kernel_version} 4.9; then 216 return 0 217 else 218 return 1 219 fi 220 } 221 222 install_elrepo() { 223 224 if centosversion 5; then 225 echo -e "${red}error:${plain} not supported centos 5." 226 exit 1 227 fi 228 229 rpm --import https://www.elrepo.org/rpm-gpg-key-elrepo.org 230 231 if centosversion 6; then 232 rpm -uvh https://www.elrepo.org/elrepo-release-6-9.el6.elrepo.noarch.rpm 233 elif centosversion 7; then 234 rpm -uvh https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm 235 fi 236 237 if [ ! -f /etc/yum.repos.d/elrepo.repo ]; then 238 echo -e "${red}error:${plain} install elrepo failed, please check it." 239 exit 1 240 fi 241 } 242 243 sysctl_config() { 244 sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf 245 sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf 246 echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf 247 echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf 248 sysctl -p >/dev/null 2>&1 249 } 250 251 install_config() { 252 if [[ x"${release}" == x"centos" ]]; then 253 if centosversion 6; then 254 if [ ! -f "/boot/grub/grub.conf" ]; then 255 echo -e "${red}error:${plain} /boot/grub/grub.conf not found, please check it." 256 exit 1 257 fi 258 sed -i 's/^default=.*/default=0/g' /boot/grub/grub.conf 259 elif centosversion 7; then 260 if [ ! -f "/boot/grub2/grub.cfg" ]; then 261 echo -e "${red}error:${plain} /boot/grub2/grub.cfg not found, please check it." 262 exit 1 263 fi 264 grub2-set-default 0 265 fi 266 elif [[ x"${release}" == x"debian" || x"${release}" == x"ubuntu" ]]; then 267 /usr/sbin/update-grub 268 fi 269 } 270 271 reboot_os() { 272 echo 273 echo -e "${green}info:${plain} the system needs to reboot." 274 read -p "do you want to restart system? [y/n]" is_reboot 275 if [[ ${is_reboot} == "y" || ${is_reboot} == "y" ]]; then 276 reboot 277 else 278 echo -e "${green}info:${plain} reboot has been canceled..." 279 exit 0 280 fi 281 } 282 283 install_bbr() { 284 check_bbr_status 285 if [ $? -eq 0 ]; then 286 echo 287 echo -e "${green}info:${plain} tcp bbr has already been installed. nothing to do..." 288 exit 0 289 fi 290 check_kernel_version 291 if [ $? -eq 0 ]; then 292 echo 293 echo -e "${green}info:${plain} your kernel version is greater than 4.9, directly setting tcp bbr..." 294 sysctl_config 295 echo -e "${green}info:${plain} setting tcp bbr completed..." 296 exit 0 297 fi 298 299 if [[ x"${release}" == x"centos" ]]; then 300 install_elrepo 301 [ ! "$(command -v yum-config-manager)" ] && yum install -y yum-utils > /dev/null 2>&1 302 [ x"$(yum-config-manager elrepo-kernel | grep -w enabled | awk '{print $3}')" != x"true" ] && yum-config-manager --enable elrepo-kernel > /dev/null 2>&1 303 if centosversion 6; then 304 if is_64bit; then 305 rpm_kernel_name="kernel-ml-4.18.20-1.el6.elrepo.x86_64.rpm" 306 rpm_kernel_devel_name="kernel-ml-devel-4.18.20-1.el6.elrepo.x86_64.rpm" 307 rpm_kernel_url_1="http://repos.lax.quadranet.com/elrepo/archive/kernel/el6/x86_64/rpms/" 308 else 309 rpm_kernel_name="kernel-ml-4.18.20-1.el6.elrepo.i686.rpm" 310 rpm_kernel_devel_name="kernel-ml-devel-4.18.20-1.el6.elrepo.i686.rpm" 311 rpm_kernel_url_1="http://repos.lax.quadranet.com/elrepo/archive/kernel/el6/i386/rpms/" 312 fi 313 rpm_kernel_url_2="https://dl.lamp.sh/files/" 314 wget -c -t3 -t60 -o ${rpm_kernel_name} ${rpm_kernel_url_1}${rpm_kernel_name} 315 if [ $? -ne 0 ]; then 316 rm -rf ${rpm_kernel_name} 317 wget -c -t3 -t60 -o ${rpm_kernel_name} ${rpm_kernel_url_2}${rpm_kernel_name} 318 fi 319 wget -c -t3 -t60 -o ${rpm_kernel_devel_name} ${rpm_kernel_url_1}${rpm_kernel_devel_name} 320 if [ $? -ne 0 ]; then 321 rm -rf ${rpm_kernel_devel_name} 322 wget -c -t3 -t60 -o ${rpm_kernel_devel_name} ${rpm_kernel_url_2}${rpm_kernel_devel_name} 323 fi 324 if [ -f "${rpm_kernel_name}" ]; then 325 rpm -ivh ${rpm_kernel_name} 326 else 327 echo -e "${red}error:${plain} download ${rpm_kernel_name} failed, please check it." 328 exit 1 329 fi 330 if [ -f "${rpm_kernel_devel_name}" ]; then 331 rpm -ivh ${rpm_kernel_devel_name} 332 else 333 echo -e "${red}error:${plain} download ${rpm_kernel_devel_name} failed, please check it." 334 exit 1 335 fi 336 rm -f ${rpm_kernel_name} ${rpm_kernel_devel_name} 337 elif centosversion 7; then 338 yum -y install kernel-ml kernel-ml-devel 339 if [ $? -ne 0 ]; then 340 echo -e "${red}error:${plain} install latest kernel failed, please check it." 341 exit 1 342 fi 343 fi 344 elif [[ x"${release}" == x"debian" || x"${release}" == x"ubuntu" ]]; then 345 [[ ! -e "/usr/bin/wget" ]] && apt-get -y update && apt-get -y install wget 346 echo -e "${green}info:${plain} getting latest kernel version..." 347 get_latest_version 348 if [ -n ${modules_deb_name} ]; then 349 wget -c -t3 -t60 -o ${deb_kernel_modules_name} ${deb_kernel_modules_url} 350 if [ $? -ne 0 ]; then 351 echo -e "${red}error:${plain} download ${deb_kernel_modules_name} failed, please check it." 352 exit 1 353 fi 354 fi 355 wget -c -t3 -t60 -o ${deb_kernel_name} ${deb_kernel_url} 356 if [ $? -ne 0 ]; then 357 echo -e "${red}error:${plain} download ${deb_kernel_name} failed, please check it." 358 exit 1 359 fi 360 [ -f ${deb_kernel_modules_name} ] && dpkg -i ${deb_kernel_modules_name} 361 dpkg -i ${deb_kernel_name} 362 rm -f ${deb_kernel_name} ${deb_kernel_modules_name} 363 else 364 echo -e "${red}error:${plain} os is not be supported, please change to centos/debian/ubuntu and try again." 365 exit 1 366 fi 367 368 install_config 369 sysctl_config 370 reboot_os 371 } 372 373 374 clear 375 echo "---------- system information ----------" 376 echo " os : $opsy" 377 echo " arch : $arch ($lbit bit)" 378 echo " kernel : $kern" 379 echo "----------------------------------------" 380 echo " auto install latest kernel for tcp bbr" 381 echo 382 echo " url: https://teddysun.com/489.html" 383 echo "----------------------------------------" 384 echo 385 echo "press any key to start...or press ctrl+c to cancel" 386 char=`get_char` 387 388 install_bbr 2>&1 | tee ${cur_dir}/install_bbr.log
也可以采用在线安装的方式:
wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh && chmod +x bbr.sh && ./bbr.sh
安装完成后,脚本会提示需要重启 vps,输入 y 并回车后重启。
重启完成后,进入 vps,验证一下是否成功安装最新内核并开启 tcp bbr,输入命令:
uname -r
查看内核版本,显示为最新版就表示 ok了
sysctl net.ipv4.tcp_available_congestion_control 返回值一般为: net.ipv4.tcp_available_congestion_control = bbr cubic reno 或者为: net.ipv4.tcp_available_congestion_control = reno cubic bbr ================================================================================= sysctl net.ipv4.tcp_congestion_control 返回值一般为: net.ipv4.tcp_congestion_control = bbr ================================================================================= sysctl net.core.default_qdisc 返回值一般为: net.core.default_qdisc = fq ================================================================================== lsmod | grep bbr 返回值有 tcp_bbr 模块即说明 bbr 已启动。注意:并不是所有的 vps 都会有此返回值,若没有也属正常。
另外:
附上大佬的centos 下最新版内核 headers 安装方法
本来打算在脚本里直接安装 kernel-ml-headers,但会出现和原版内核 headers 冲突的问题。因此在这里添加一个脚本执行完后,手动安装最新版内核 headers 之教程。 执行以下命令 yum --enablerepo=elrepo-kernel -y install kernel-ml-headers 根据 centos 版本的不同,此时一般会出现类似于以下的错误提示: error: kernel-ml-headers conflicts with kernel-headers-2.6.32-696.20.1.el6.x86_64 error: kernel-ml-headers conflicts with kernel-headers-3.10.0-693.17.1.el7.x86_64 因此需要先卸载原版内核 headers ,然后再安装最新版内核 headers。执行命令: yum remove kernel-headers 确认无误后,输入 y,回车开始卸载。注意,有时候这么操作还会卸载一些对内核 headers 依赖的安装包,比如 gcc、gcc-c++ 之类的。不过不要紧,我们可以在安装完最新版内核 headers 后再重新安装回来即可。 卸载完成后,再次执行上面给出的安装命令。 yum --enablerepo=elrepo-kernel -y install kernel-ml-headers 成功安装后,再把那些之前对内核 headers 依赖的安装包,比如 gcc、gcc-c++ 之类的再安装一次即可。 为什么要安装最新版内核 headers 呢? 这是因为 ss-libev 版有个 tcp fast open 功能,如果不安装的话,这个功能是无法开启的。 内核升级方法 如果是 centos 系统,执行如下命令即可升级内核: yum -y install kernel-ml kernel-ml-devel 如果你还手动安装了新版内核 headers ,那么还需要以下命令来升级 headers : yum -y install kernel-ml-headers centos 6 的话,执行命令: sed -i 's/^default=.*/default=0/g' /boot/grub/grub.conf centos 7 的话,执行命令: grub2-set-default 0 如果是 debian/ubuntu 系统,则需要手动下载最新版内核来安装升级。 去这里下载最新版的内核 deb 安装包。 如果系统是 64 位,则下载 amd64 的 linux-image 中含有 generic 这个 deb 包; 如果系统是 32 位,则下载 i386 的 linux-image 中含有 generic 这个 deb 包; 安装的命令如下(以最新版的 64 位 4.12.4 举例而已,请替换为下载好的 deb 包): dpkg -i linux-image-4.12.4-041204-generic_4.12.4-041204.201707271932_amd64.deb 安装完成后,再执行命令: /usr/sbin/update-grub 最后,重启 vps 即可。 特别说明 如果你使用的是 google cloud platform (gcp)更换内核,有时会遇到重启后,整个磁盘变为只读的情况。只需执行以下命令即可恢复: mount -o remount rw /
参考链接:
https://github.com/google/bbr/blob/master/documentation/bbr-quick-start.md
下一篇: hive内置方法一览