zoukankan      html  css  js  c++  java
  • 谷歌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='33[0;31m'
     13 green='33[0;32m'
     14 yellow='33[0;33m'
     15 plain='33[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 "
    ------------ ${soft} setting ------------
    "
     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 "
    your selection: $hint
    "
    121 }
    122 
    123 version_ge(){
    124     test "$(echo "$@" | tr " " "
    " | 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
    View Code

    也可以采用在线安装的方式:

    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
    http://elrepo.org/tiki/tiki-index.php
    http://kernel.ubuntu.com/~kernel-ppa/mainline/

    https://teddysun.com/489.html

     

  • 相关阅读:
    数据库中char、varchar、varchar2、nvarchar之间的关系
    Oracle中scott用户下基本表练习SQL语句
    判断一个数是否是素数
    阿里P7前端需要哪些技能
    react Native 踩坑记录
    流程节点(2018.7.31)
    在centos7下手工安装和配置Nginx
    微信公众号开发
    nodejs 实战
    数据库权限表的设计
  • 原文地址:https://www.cnblogs.com/thelovelybugfly/p/12199042.html
Copyright © 2011-2022 走看看