一日,正在紧张的工作中,突然收到反馈。在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方式,问题解决。

文章来源于腾讯云开发者社区,点击查看原文