一日,正在紧张的工作中,突然收到反馈。在windows系统使用python SDK时出现read time out问题,投入调查。
问题背景:某客户在初次使用COS时,测试上传功能失败,因环境配置较为特殊(云CVM Linux系统中虚拟windows系统),且报错内显示COSClientError错误,且显示HTTPSConnectionPool的443端口信息,怀疑是网络问题导致。
简易架构图
排查:
链路检查
1.telnet COS默认域名80和443端口,正常。
2.测试访问https和http的V5域名资源下载,正常。
3.测试使用控制台和可视化COS browser工具上传文件,正常。
网络链路正常,继续检查SDK,执行putobject时抓包
使用fiddler协议上传时抓包
这里看到,请求的body为空,Content-Length:40,由于请求时间过长,被server端主动关闭,返回408 Request body incomplete。
基本确定,是在SDK请求时,出现的上传超时并且body为空。接下来只能检查代码了。
代码片段
secret_id = 'xxxx' # 替换为用户的secret_id
secret_key = 'xxxx' # 替换为用户的secret_key
region = 'ap-beijing' # 替换为用户的region
token = None # 使用临时秘钥需要传入Token,默认为空,可不填
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
# 文件流 简单上传
file_name = '1.txt'
with open('1.txt', 'r') as fp:
response = client.put_object(
Bucket='xxxx-xxxx', # Bucket由bucketname-appid组成
Body=fp,
Key=file_name,
StorageClass='STANDARD',
ContentType='text/html; charset=utf-8'
)
print(response['ETag'])
拿到测试后发现确实read time out。但官网的DEMO上传是正常的。
对比发现
问题已经定位(上面图的红框部分),那么b和rb有什么区别呢。
在python中:
r是表示默认文本方式读取数据。
rb是表示读取二进制数据,b是binary(二进制)的意思。
基于http协议的网络传输上传时,会向服务器传送Content-Length属性头,这就需要完整读取文件,用r进行读文件操作时,直到读到文档结束符(EOF)才算读取到文件最后,Python会认为字节\x1A(26)转换成的字符为文档结束符(EOF),所以进行读取二进制文件时,可能会出现文档读取不全的现象。就会导致hang住最终timeout。
从现有比较流行的python 公共库中也可以看到说明
至此,改用rb方式,问题解决。