序文
プロジェクト内の oss サーバーは今後も更新を続ける予定がないため、すべてのファイルをローカルにバックアップして保存したいと考えています
いくつかの公式文書の手法を比較検討した結果、関数計算の手法を選択しました。
主な理由は、当時 1 つのバケットが適切に処理されず、すべてのファイルがサブディレクトリではなくバケットのルート ディレクトリに保存されていたため、ダウンロードするファイルやディレクトリを直接選択することができなかったことです (数十のバケットがあるため)ルート ディレクトリに数千のファイルがあります)
ステップ
まず、公式ドキュメントに従ってFunction Compute をデプロイします
ピットを踏み始めます
-
Function Compute は正常にデプロイされましたが、実行するテスト コードをクリックすると、次のようにエラーが報告されます。
{ "errorMessage": "No JSON object could be decoded", "errorType": "ValueError", "stackTrace": [ [ "\\u00a0\\u00a0File \"/code/main.py\"", "line 28", "in main_handler", "evt = json.loads(request_body)" ], [ "\\u00a0\\u00a0File \"/var/fc/lang/python2/lib/python2.7/json/__init__.py\"", "line 339", "in loads", "return _default_decoder.decode(s)" ], [ "\\u00a0\\u00a0File \"/var/fc/lang/python2/lib/python2.7/json/decoder.py\"", "line 364", "in decode", "obj, end = self.raw_decode(s, idx=_w(s, 0).end())" ], [ "\\u00a0\\u00a0File \"/var/fc/lang/python2/lib/python2.7/json/decoder.py\"", "line 382", "in raw_decode", "raise ValueError(\"No JSON object could be decoded\")" ] ] }
その理由は、ファイルを読み取ることができないためです
event.json
。Alibaba Cloud のアフターセールス エンジニアに相談した結果、現在のバージョンを読み取ることができないため、コードを変更して json 設定をファイルpython2.7
に直接書き込む必要があるという結論になりました。main
コードは次のとおりです。
main.py
ファイルの約 20 ~ 40 行です。変更された位置についてはコメントを参照してください。def main_handler(environ, start_response): LOG.info('event: %s', environ) try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 request_body = environ['wsgi.input'].read(request_body_size) # 这一行注释的原因是因为python2的运行环境中 wsgi.input确实不能接收配置了. 这里接收配置主要是wsgi接收 event.json # evt = json.loads(request_body) evt = { "region": "cn-zhangjiakou", "bucket": "zhushang-applet-code", "source-dir": "test/" } context = environ['fc.context'] oss_client = get_oss_client(evt, context) ret = _main_handler(oss_client, evt, context) status = '302 FOUND' response_headers = [('Location',sign_url(oss_client, ret))] start_response(status, response_headers) return "ok"
-
公式ドキュメントによると、ルートディレクトリにファイルをダウンロードしたい場合は、次のようにする
./
ことができます。
実際、彼に従って修正した後、実行しても機能しませんでした。22B
解凍できない圧縮パッケージをローカルにダウンロードすると、OSS には対応する圧縮パッケージがありませんでした。つまり、失败了
最終的に、さまざまなテストを行った結果、
""
空の文字列をディレクトリとして使用できることがわかりました。コードは以下のように表示されます
evt = { "region": "cn-zhangjiakou", "bucket": "zhushang-applet-code", "source-dir": "" }
-
ダウンロードしたファイルを圧縮して圧縮すると大きすぎるため、失敗します。
コードを実行すると、次のようなエラーが発生します。
Zipfile size would require ZIP64 extensions
{ "errorMessage": "Zipfile size would require ZIP64 extensions", "errorType": "LargeZipFile", "stackTrace": [ [ "\\u00a0\\u00a0File \"/code/main.py\"", "line 37", "in main_handler", "ret = _main_handler(oss_client, evt, context)" ], [ "\\u00a0\\u00a0File \"/code/main.py\"", "line 52", "in _main_handler", "return zip_files(oss_client, source_dir, source_files, dest_file)" ], [ "\\u00a0\\u00a0File \"/code/main.py\"", "line 116", "in zip_files", "task_q.run()" ], [ "\\u00a0\\u00a0File \"/code/task_queue.py\"", "line 40", "in run", "raise self.__exc_info[1]" ] ] }
Python 2.7 スクリプトの制限により、2G を超えるとこのエラーが報告され、4G に増やすには構成を変更する必要があると記載されています (
但是实际上我压缩了20多个G的也是可以的
)コードを次のように変更し、
main.py
ファイルの80-100
行の前後のこの関数の行を変更します。def producer(queue): mem_buf = MemBuffer(queue) # 默认的压缩文件最大只支持2G,使用这个方式可以做到支持4G zip_file = StreamZipFile(mem_buf, 'w', allowZip64=True) if isinstance(source_files, list): for obj in source_files: zip_add_file(zip_file, obj) elif isinstance(source_dir, basestring): for obj in oss2.ObjectIterator(oss_client, prefix=source_dir): zip_add_file(zip_file, obj.key) else: raise Exception('either `source_files` or `source_dir` must be speicified') zip_file.close() mem_buf.flush_buffer()
-
Function Compute のデフォルトの実行時間は 10 分です。
Function Compute によって設定されるデフォルトでは、
弹性实例
最大実行時間は 10 分です。性能实例
に変更してから、実行タイムアウトを7200
秒に変更する必要があります。