作者:張醫博
淺談
很多 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 更好。
- = oss2.Auth('AK', 'SK')
- = oss2.Bucket(auth, 'endpoint', 'bucket',enable_crc=False)

問:安裝 oss2 導入出現 urllib3 不存在提示

答:
- 和之前說過的一樣,這種錯誤都是 python 自身的問題,看哪個依賴的模塊沒有,安裝即可, oss2 的 http 請求處理依賴 urllib3 。
- 確認下 pip install 安裝的環境和本地 python 環境是否一致。
問: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
- 客戶端部署 tcpdump ,然後重新運行代碼上傳,保存抓包。
案例:
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 值不一樣。