下载过程中的高延迟


9

我在5Mbps的商务连接上遇到的问题与在此站点上的另一则帖子相同。一旦任何一台计算机开始下载,经过ISP(贝尔)提供的DFG的第一跳的延迟就超出了图表。该第一跳可能在我们的同一建筑物中,并且持续1ms,开始下载,例如Windows更新,然后跳到200-1000ms。

我在电话上花费了数小时,都表示您已经达到了最大可用带宽,这是延迟增加的正常现象。但是我的阅读告诉我,他们正在用TCP破坏某些东西。我已经在家庭Shaw连接上运行了测试,甚至在运行下载的Rogers LTE上运行了测试,并为我的帐户达到了最大Mbps,但延迟没有达到极限。

我的理解是否正确?贝尔正在做一些事情来打破TCP的内置技术,根据两个端点之间的可用带宽来管理其速率?


有什么答案对您有帮助吗?如果是这样,您应该接受答案,这样问题就不会永远弹出来寻找答案。或者,您可以提供并接受自己的答案。
罗恩·莫平

Answers:


12

贝尔在告诉你真相。当您尝试将5Mbps(或更高)推送到5Mbps连接时,所有文件都整理整齐(读取:队列)。由于没有积压,您的ping不会延迟。但是,答复现在在队列的末尾。TCP确实正在执行本应做的工作-发送方正在填充允许的接收窗口。

您可以在线上做一些事情(例如QoS,WRED等)以帮助减少影响,但是当发送方和接收方带宽之间有很大差异时,您会看到这种事情。我已经使用了多年(T1、6Mbps DS3甚至10Mbps cablemodem),您可以要求ISP减少他们这一边的队列大小,但是他们不太可能这样做,因为这会导致丢包。


4
en.wikipedia.org/wiki/Bufferbloat域中包含200-1000ms(85-420个数据包,1500B @ 5Mbps) ,因为TCP取决于发生的数据包丢失才能正确,快速地设置窗口大小,因此将其减小到可能是10个数据包(25毫秒)。我完全同意,除非很多客户抱怨,否则运营商不太可能在其产品中进行更改,这可能更容易将QoS产品订购到业务连接,其缓冲值应该更合理,并且可以根据客户需求进行订购。有趣的是,当等待时间开始增加时,Google的QUIC可以选择降低传输速率。
ytti

谢谢Ricky,我听到了您在说什么,但是经过更多阅读之后,TCP的Flow Control是否不应该看到积压的日志并将窗口调整为接收方可以处理的速率?这样一来,客户端或路由器(贝尔网络上的跃点2)是否过载?在我看来,您阅读的bufferbloat似乎也已经准确地描述了该方案。
Stunpals

3
如果没有数据包丢失(或ECN),TCP将无法检测到任何瓶颈。如果路由器队列足够深,并且接收窗口足够大,则可以创建大量积压。RFC1323时间戳可能有帮助,但是我已经看到了允许Windows“使用” TS的重大问题。(它尝试通过发送初始TS = 0来“协商” TS)
Ricky Beam

4

如今,大多数形式的“ QoS”都不包含AQM,因为供应商发现很难自动配置RED而不造成损害。这导致了当今许多常见设备(尤其是电缆调制解调器和无线设备)上出现的可怕延迟。因此,仅建议“打开Qos” ...无济于事。实际上,至少在Netgear的一种产品上,为“ QoS”打开速率限制器会导致更糟糕的结果……。

最近,出现了一种新的公平排队+ AQM算法,该算法确实运行得非常好,而且更好,除了设置速率限制器外几乎不需要任何配置。它被称为fq_codel,现在在大多数Linux中都可以广泛使用,并且也已移植到BSD。它是openwrt屏障断路器,后院和gargoyle中默认“ QoS”的一部分,石像鬼使用的是称为sfqred的(相当不错)的早期版本,带有一个创新的自动速率调整方案,称为ACC。

因此,您可以在行为不当的链接之前基于此框,打开其QoS速率限制器(将其设置为略低于提供商的入站和出站设置,以便您控制)+ fq_codel,并为使用它的每个人获得更好的性能。我的意思是惊人的好:请参阅下面的ietf演示,向ietf的iccrg工作组提交的报告,等等。

有关bufferbloat问题及其修复方法的更多详细信息,请参见:

http://www.bufferbloat.net/projects/cerowrt/wiki/Bloat-videos

我们(当然)试图说服各种ISP CPE供应商注意,Cablelabs也在几个月前发表了一篇关于这一新东西的精彩研究,其中还包含了有关当前特别是电缆调制解调器的不良行为的一些详细信息。

http://www.cablelabs.com/downloads/pubs/Active_Queue_Management_Algorithms_DOCSIS_3_0.pdf


1

您所看到的完全是典型的。许多服务提供商将对速率进行限制和/或使用QoS机制来降低ICMP的优先级(包括传统的ping和traceroute),因为它有时被用于拒绝服务攻击。

虽然链接不拥塞,但较低的优先级不会影响任何内容,因为没有流量在排队。在这些期间,由于ICMP数据包将立即转发且完全不会延迟,因此您的等待时间仍然很短。

当链接拥塞时,优先级较高的队列会受到更多关注。根据排队机制的不同,它可能针对来自优先级较低的队列的每个数据包转发来自优先级较高的队列的多个数据包,甚至可能仅在优先级较高的队列中没有任何内容时才转发。在任何情况下,降级到较低优先级队列的数据包通常比没有拥塞的链路保留的时间更长,从而增加了延迟。


1
感谢YLearn的答复。我确实获得了ICMP的优先权,但我们可以看到其他流量受到影响,而ICMP只是用来说明问题。正如我试图传达给Ricky的那样,在我的评论中是Flow Control是TCP起作用的原因,因为如果Flow Control无法正常工作,则任何带宽高于接收者的发送者都会使他脱机DOS。那就是为什么拨号上网可以通过1000Mbps连接进行通信?如果文件传输过程中的运行延迟达到了适当的标准,我是否在错误地思考,以保持可共鸣的水平,而不是冒顶?
Stunpals

1

您可能正在遭受缓冲膨胀的困扰,并且您需要AQM(活动队列管理)。我已经为Linux编写了一个脚本,这使得这很容易:

#!/bin/bash
# Traffic shaping script (AQM, fq_codel+tbf)
# Copyright 2018 Mikko Rantalainen <mikko.rantalainen@gmail.com>
# License: MIT (X11)
# Usage:
#   21/0.8 Mbps connection (ADSL2): DOWNLINK_RATE=21.7Mbit UPLINK_RATE=0.8Mbit TBF_LATENCY=500ms bin/traffic-shaping start
#   100/100 Mbps connection: ./traffic-shaping
#   1/1 GBps connection: DOWNLINK_RATE=1Gbit UPLINK_RATE=1Gbit TBF_LATENCY=10ms bin/traffic-shaping start
# Note that using low TBF_LATENCY will require powerful CPU.
#   

set -e

DEV="${DEV:=$(ip route | grep "^default " | grep -Po "(?<=dev )[^ ]+")}"

# ingress:
DOWNLINK_RATE="${DOWNLINK_RATE:=104000kbit}" # or e.g. "21.5Mbit"
# egress:
UPLINK_RATE="${UPLINK_RATE:=105000kbit}"

CODEL_INTERVAL="${CODEL_INTERVAL:=100ms}" # usually 100ms, high speed links with low latency may need lower values
CODEL_TARGET="${CODEL_TARGET:=5ms}" # unit "us" is also available, usually 5%-10% of CODEL_INTERVAL
CODEL_LIMIT="${CODEL_LIMIT:=1001}" # decrease to reduce latency, too low values will limit throughput
CODEL_FLOWS="${CODEL_FLOWS:=1024}"

# set burst as high as possible without causing dropped packets at the start of the connections
DOWNLINK_BURST="${DOWNLINK_BURST:=6500}"
UPLINK_BURST="${UPLINK_BURST:=6500}"

TBF_LATENCY="${TBF_LATENCY:=14ms}" # set to lower latency to improve control over bandwidth limiting, UPLINK_BURST bytes must be able to be sent in this time

IFB="$DEV.ingress"

INITCWND="${INITCWND:=20}"
INITRWND="${INITRWND:=20}"

configure_shaping()
{
    # EGRESS (outgoing traffic, "uploads"):

    # setup bandwidth limiting:
    tc qdisc add dev "$DEV" root handle 1: tbf rate "$UPLINK_RATE" burst "$UPLINK_BURST" latency "$TBF_LATENCY"

    # setup fq_codel for bandwidth shaping
    tc qdisc add dev "$DEV" parent 1: fq_codel limit "$CODEL_LIMIT" target "$CODEL_TARGET" interval "$CODEL_INTERVAL" flows "$CODEL_FLOWS" noecn


    # INGRESS (incoming traffic, "downloads"):

    # setup bandwidth limiting (ingress limiting needs IFB or Intermediate Functional Block, see https://wiki.linuxfoundation.org/networking/ifb):
    tc qdisc add dev "$DEV" handle ffff: ingress
    ip link add name "$IFB" type ifb
    tc qdisc add dev "$IFB" root handle 1: tbf rate "$DOWNLINK_RATE" burst "$DOWNLINK_BURST" latency "$TBF_LATENCY"

    # setup fq_codel for bandwidth shaping
    tc qdisc add dev "$IFB" parent 1: fq_codel limit "$CODEL_LIMIT" target "$CODEL_TARGET" interval "$CODEL_INTERVAL" flows "$CODEL_FLOWS" ecn
    ip link set dev "$IFB" up

    # connect ingress filtering to actual WAN device
    tc filter add dev "$DEV" parent ffff: protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev "$IFB"

    # configure initcwnd and initrwnd
    ip route change $(ip route | grep ^default) initcwnd "$INITCWND" initrwnd "$INITRWND"
}

remove_shaping()
{
    tc qdisc list | grep -q "ingress" && tc qdisc del dev "$DEV" ingress || true
    tc qdisc list | grep -q "codel" && tc qdisc del dev "$DEV" root || true
    ip link show | grep -q "$IFB" && ip link del "$IFB" || true
}

status()
{
        echo "─── queue discipline configuration: ──────────────────"
        tc qdisc list
        echo "   TIP: use e.g. 'sudo tc qdisc del dev $DEV ingress' to remove ingress filtering"
        echo "   TIP: use e.g. 'sudo tc qdisc del dev $DEV root' to remove egress filtering"
        echo "─── ip link show: ────────────────────────────────────"
        ip link show
        echo "   TIP: use e.g. 'sudo ip link del $IFB' to remove ingress device"
}

color_status()
{
    status | grep --color=auto -E "^|$DEV|$IFB|rate [^ ]+"
}

# handle parameters

ACTION="$1"
shift || true

while [ ! -z "$1" ]
do
    case "$1" in
        -v|--verbose)
            echo "Device: $DEV"
            echo "Downlink rate (ingress): $DOWNLINK_RATE"
            echo "Uplink rate (egress): $UPLINK_RATE"
            set -x
            ;;
        *)
            if [ ! -z "$2" ]; then
                echo "Unknown parameter: '$2'" 1>&2
                exit 1
            fi
            ;;
    esac
    shift
done

case "$ACTION" in
    start)
        remove_shaping
        configure_shaping
        ;;
    stop)
        remove_shaping
        ;;
    status)
        color_status
        ;;
    restart)
        remove_shaping
        configure_shaping
        ;;
    *)
        echo "Unknown action: $1" 1>&2
        echo "Usage: $0 <start|stop|restart|status> [--verbose|-v]" 1>&2
        exit 1
esac

您只需将脚本另存为traffic-shapingchmod a+x以root身份运行(显然,在阅读源代码之后)。

对于您的用例,我建议

DOWNLINK_RATE=5.0Mbit UPLINK_RATE=5.0Mbit TBF_LATENCY=500ms ./traffic-shaping start


请注意,您可能需要运行linux-lowlatency内核以使系统保持处理所有软件包的任务。
Mikko Rantalainen


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.