OSS Python SDK

作者:张医博

浅谈

很多 oss 使用者在使用 Python SDK 时出现很多问题,不确定是否影响使用,有的安装失败环境有问题,今天说下遇到的几个案例

官方安装

  • pip install oss2
  • 版本最好是 2.7.5 或以上

oss2 依赖

  • 如果要开启 crc64 循环冗余校验,需要先将 crcmod 安装好。
  • 安装 python-devel 执行 yum install python-devel。
  • 需要循环冗余校验,安装 crcmod 执行 pip install crcmod。

安装遇到的问题

验证 oss2

先判断是 oss2 是否安装成功,在命令行输入python并回车,进入Python环境,执行以下命令检查SDK版本:

>>> import oss2
>>> oss2.__version__
'2.x.x'

导入 crcmod 失败

>>> import crcmod._crcfunext
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named _crcfunext
  • 没有安装 python-devel 或者 crcmod ,如果已经安装 crcmod ,请 uninstall 后,重新安装 python-devel 然后再安装 crcmod。
  • crcmod 安装的环境 path 和你本机的 python 环境不一致,可以用 sys path 查看你 python 加载的环境变量路径确认一下。
  • 参考一些网上的处理方法,这是个开源的报错 参考

使用遇到问题排查

问:同台机器 ossutil 很快,python SDK 很慢

  • ossutil 源码是 go ,并发上传的性能确实很好,但是 python SDK 也至于慢很多,一般这种情况基本都是默认开启了 crc64 。
  • 如果对性能有要求的话,建议把 crc64 关掉,通过在 header 头中增加 Content-md5 头的方式替代 crc64 更好。
  1. = oss2.Auth('AK', 'SK')
  2. = oss2.Bucket(auth, 'endpoint', 'bucket',enable_crc=False)

OSS Python SDK

问:安装 oss2 导入出现 urllib3 不存在提示

OSS Python SDK

答:

  • 和之前说过的一样,这种错误都是 python 自身的问题,看哪个依赖的模块没有,安装即可, oss2 的 http 请求处理依赖 urllib3 。
  • 确认下 pip install 安装的环境和本地 python 环境是否一致。

问:OSS python SDK 分片上传失败

OSS Python SDK

用户通过 python SDK 的分片上传函数上传到 OSS 失败,碎片管理中出现很对碎片。

  • 先确认是直接传到 OSS,还是通过其他 proxy 传输到 OSS (类似 CDN),如果经过 CDN 再上传到 OSS 需要在 OSS 上配置跨域的头,Access-Control-Allow-Origin 、Access-Control-Allow-Mehtod 、Access-Control-Allow-header,并且将 Etag 暴露出去。
  • 客户端上传失败是因为网络超时,还是捕获到异常上传失败,需要详细看下捕获到的 SDK 异常信息分析,如果是网络超时导致上传失败,建议使用断点续传来替代普通上传。断点续传支持分片,并发,已经弱网的兼容。
  • 清理掉上传失败的碎片文件重新上传。
  • 当以上操作都解决不了你的问题时,需要提供以下信息升级阿里云便于快速定位:
    • 提供 SDK 异常时返回的 requestID,这个属性是 response header 中携带的记录了完整的 OSS 请求过程。
    • 客户端部署 tcpdump ,然后重新运行代码上传,保存抓包。
      tcpdump -i <网卡出口名称> -s0 host <访问oss的域名> -w faild.pcap

案例:

Centos 机器上执行分片上传 SDK 问题正常,但是 ubuntu 机器上传总是报 403 失败。

分析:

首先出现问题后,如果在 ubuntu 机器上,操作 OSS 出现 403 ,OSS 服务端会返回 403 对应的 OSS requestID,里面包含了 403 的原因,需要提供给阿里云排查。

客户端部署 tcpdump 抓包,可以通过 tcp 报文排查是否由于 header 头信息不对引起的计算签名与服务端不匹配。

POST /ttsservice%2Fpasswd?uploadId=D468E486D1D94D90A1AB8885A4E32AE0 HTTP/1.1
Host: rokid.oss-cn-hangzhou.aliyuncs.com
Accept-Encoding: identity
Accept: */*
Content-Length: 137
date: Sat, 29 Dec 2018 07:32:34 GMT
authorization: OSS LTAIknFr:r2KPR0y4E0G5tnU/MYdcvXHPQQ4=
Content-Type: application/x-www-form-urlencoded
User-Agent: aliyun-sdk-python/2.6.0(Linux/4.4.0-31-generic/x86_64;3.4.3)

<CompleteMultipartUpload><Part><PartNumber>1</PartNumber><ETag>"3195544E19D99658706D51EF5"</ETag></Part></CompleteMultipartUpload>HTTP/1.1 403 Forbidden

Server: AliyunOSS
Date: Sat, 29 Dec 2018 07:33:43 GMT
Content-Type: application/xml
Content-Length: 1122
Connection: keep-alive
x-oss-request-id: 5C2723573183A12D
x-oss-server-time: 0

<?xml version="1.0" encoding="UTF-8"?>
<Error>
 <Code>SignatureDoesNotMatch</Code>
 <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
 <RequestId> 5C2723573183A12D </RequestId>
 <HostId>rokid.oss-cn-hangzhou.aliyuncs.com</HostId>
 <OSSAccessKeyId> LTAIknFr </OSSAccessKeyId>
 <SignatureProvided>r2KPR0y4E0G5tnU/MYdcvXHPQQ4=</SignatureProvided>
 <StringToSign>POST
application/x-www-form-urlencoded
Sat, 29 Dec 2018 07:32:34 GMT
/rokid/ttsservice/passwd?uploadId=D468E486D1D94D90A1AB8885A4E32AE0</StringToSign>
 <StringToSignBytes>50 4F 53 54 0A 0A 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 2D 77 77 77 2D 66 6F 72 6D 2D 75 72 6C 65 6E 63 6F 64 65 64 0A 53 61 74 2C 20 32 39 20 44 65 63 20 32 30 31 38 20 30 37 3A 33 32 3A 33 34 20 47 4D 54 0A 2F 72 6F 6B 69 64 2D 6F 70 73 2D 6D 6F 64 65 6C 2F 74 74 73 73 65 72 76 69 63 65 2F 70 61 73 73 77 64 3F 75 70 6C 6F 61 64 49 64 3D 44 34 36 38 45 34 38 36 44 31 44 39 34 44 39 30 41 31 41 42 38 38 38 35 41 34 45 33 32 41 45 30 </StringToSignBytes>
</Error>
  • 如上是客户端抓到的报文信息,我们主要是分析请求头的信息。拿到请求后,带入到以下脚本中,看下计算出来的结果是否和 SDK 一致。如果一致说明 SDK 的计算是正确的,那么如果服务端收到的和客户端计算的 signature 还不一致说明请求的内容可能被网络中设备改动过,可以使用 https 的方式上传。
import base64
import hmac
import sha
mac = hmac.new("<Secretkey>","POST\n\napplication/x-www-form-urlencoded\nSat, 29 Dec 2018 07:32:34 GMT\n/rokid/ttsservice/passwd?uploadId=D468E486D1D94D90A1AB8885A4E32AE0", sha)
Signature = base64.b64encode(mac.digest())
print(Signature)
  • 如果抓包中和脚本中计算的结果不一致,有可能存在 SDK 在 ubuntu 平台编译的适配问题导致 MD5 值不一样。
上一篇:OSS signature 计算


下一篇:mysql的Join算法