技术解析
受影响范围从 python v3.6.0b1 开始,导致测速出问题的提交的 commit id 是 3c0d0baf2badfad7deb346d1043f7d83bb92691f。准确来说,是因为 urllib 更新后 speedtest 没有对相应功能做更新。
从系统受影响版本上来看,由于 ubuntu18.04 的包总是比较新,python3 的版本超过了 v3.6.0b1 ,而用 apt 安装的 speedtest,/usr/bin/speedtest 会要求使用 python3,所以会导致上传出问题。。
如果是 ubuntu16.04 ,python3 的版本是 3.5.2,所以没事。centos 一堆老包,应该也不会受影响。其他 linux 发行版没测试,可以自己的用 python3 --version 看看。
可以直接用 python2 执行:
liuxu:~$ dpkg -L speedtest-cli
/usr/lib/python2.7/dist-packages/speedtest_cli.py
liuxu:~$ python2 /usr/lib/python2.7/dist-packages/speedtest_cli.py
可以直接使用我的 github,我已经修复这个问题了,也 pull request 到上游了,看他们用不用吧:
liuxu:speedtest$ wget -O speedtest-cli https://raw.githubusercontent.com/liuquanhao/speedtest-cli/master/speedtest.py
liuxu:speedtest$ chmod +x speedtest-cli
也可以自己修改,代码在Speedtest::upload()
中。
原代码:
...
requests.append(
(
build_request(self.best['url'], data, secure=self._secure),
size
)
)
def producer(q, requests, request_count):
for i, request in enumerate(requests[:request_count]):
修复后的代码,就添加了下 headers:
...
headers = {'Content-length': size}
requests.append(
(
build_request(self.best['url'], data, secure=self._secure, headers=headers),
size
)
)
def producer(q, requests, request_count):
for i, request in enumerate(requests[:request_count]):
github 相关提交在这里:3c0d0baf2badfad7deb346d1043f7d83bb92691f
主要是因为 urllib.request.AbstractHTTPHandler::do_request_()添加了'Transfer-encoding: chunked'相关代码,如果没有设置Content-length
,就会设置Transfer-encoding
。一旦连接使用了 chunked,speedtest 上传线程的前 2 个一直阻塞到 timeout,导致只能统计到前 2 次的上传。解决这个问题,只需要按前面的在上传时给 request 设置好 Content-length 头即可。
相关详细啰嗦的一堆,可以看我的博客。顺便可以来个友链,要求类型为电影欣赏 /旅游摄影 /开发 /网络相关技术,超过 30 篇,月更新不低于 1 篇。