クラウド・ランの32 MB要求制限を克服する方法
21071 ワード
Cloud Run Google Serverによって提供される素晴らしいServerlessな製品は、しばしばコンテナ化されたウェブサービスを走らせるのにぴったりです.これは、自動スケーリング、ローリングの更新、Autorestartなどの多くの利点を提供し、スケール0にわずか数名に.すべてのクラスタのプロビジョニングと管理の面倒なし!
この製品は、PythonのフラスコREST APIとして、次のようなデザインで確実に選択します.
1 -残りのエンドポイントにHTTP POSTでデータファイルをアップロードする
2 -プロセスファイル
3 -クライアントlibを使用してBigQueryにデータを挿入する
これは完全に罰金です.32 MBより大きいデータファイルを扱うことができない限り!
実際、クラウドランはこのような大きなファイルをアップロードしません.代わりに、エラーメッセージを取得します.
おめでとう、あなただけのハードヒットsize limit of Cloud Run inbound requests .
しかし、心配しないで、以下の改善されたデザインを適用するならば、あなたはあなたのサービスのために雲ランを使用し続けることができます:
制限を回避するには、ソリューションを設計することができますCloud Storage signed urls :
今回、ファイルは残りのエンドポイントに直接アップロードされませんが、代わりにクラウドストレージにアップロードされます.
このプロセスの欠点は、クライアントが1つの代わりに2つの要求をしなければならないということです.したがって、全く新しいシーケンスは次のようになります.
1 -クライアントが符号化されたURLを
2 -クラウドストレージクライアントを使用して、Webサービスは、署名されたURLを生成し、クライアントにそれを返します
3 -クライアントは、ファイルを直接クラウドストレージバケットにアップロードします( HTTPは署名されたURLに置かれます).
4 -ファイルアップロードの終わりに、通知
5 -通知は、その後、サブスクリプションを介してクラウドランでWebサービスにプッシュされます
6 - Webサービスは、ファイルをダウンロードして通知に反応する
7 -ウェブサービスは、ファイルを処理することができます.
8 -同様に、データはbigqueryに挿入されます
このデザインは全く無価値で、失敗のどんな一点もなしできちんとスケールします.さて、より詳細にそれを実装する方法を見てみましょう.
ちゃ!クラウドランサービスには、その役割が必要です
このPythonコードは、this blog post by Evan Peterson , クラウドのWebServiceの既定のサービスアカウントで、署名されたURLを生成する方法を公開します
インフラを持たない雲をコードとして行う堅牢な方法はないTerraform あなたのクラウドリソースを管理するための最適なツールです.
このデザインを展開するための地形図です.
つの最終的なgotcha:署名されたURLでクラウドストレージにアップロードするには、
このデザインを経験しましたか.どうやってそれを改善するの?コメントを教えてください.
デザインスキーマExcalidraw とGCPのアイコンライブラリ
カバー写真joel herzog on Unsplash
この製品は、PythonのフラスコREST APIとして、次のようなデザインで確実に選択します.
1 -残りのエンドポイントにHTTP POSTでデータファイルをアップロードする
2 -プロセスファイル
3 -クライアントlibを使用してBigQueryにデータを挿入する
これは完全に罰金です.32 MBより大きいデータファイルを扱うことができない限り!
実際、クラウドランはこのような大きなファイルをアップロードしません.代わりに、エラーメッセージを取得します.
413: Request entity too large
おめでとう、あなただけのハードヒットsize limit of Cloud Run inbound requests .
しかし、心配しないで、以下の改善されたデザインを適用するならば、あなたはあなたのサービスのために雲ランを使用し続けることができます:
改善されたデザインは、クラウドストレージ、署名のURLとPubSub通知
制限を回避するには、ソリューションを設計することができますCloud Storage signed urls :
今回、ファイルは残りのエンドポイントに直接アップロードされませんが、代わりにクラウドストレージにアップロードされます.
このプロセスの欠点は、クライアントが1つの代わりに2つの要求をしなければならないということです.したがって、全く新しいシーケンスは次のようになります.
1 -クライアントが符号化されたURLを
2 -クラウドストレージクライアントを使用して、Webサービスは、署名されたURLを生成し、クライアントにそれを返します
3 -クライアントは、ファイルを直接クラウドストレージバケットにアップロードします( HTTPは署名されたURLに置かれます).
4 -ファイルアップロードの終わりに、通知
OBJECT_FINALIZE
を送信する5 -通知は、その後、サブスクリプションを介してクラウドランでWebサービスにプッシュされます
6 - Webサービスは、ファイルをダウンロードして通知に反応する
7 -ウェブサービスは、ファイルを処理することができます.
8 -同様に、データはbigqueryに挿入されます
このデザインは全く無価値で、失敗のどんな一点もなしできちんとスケールします.さて、より詳細にそれを実装する方法を見てみましょう.
クラウドランから署名URLを作成する
ちゃ!クラウドランサービスには、その役割が必要です
roles/iam.serviceAccountTokenCreator
署名されたURLを生成できるようにします.それは本当に文書化されません、そして、あなたがそれを与えないならば、あなたは多くの情報なしでHTTPエラー403を得ます.このPythonコードは、this blog post by Evan Peterson , クラウドのWebServiceの既定のサービスアカウントで、署名されたURLを生成する方法を公開します
from typing import Optional
from datetime import timedelta
from google import auth
from google.auth.transport import requests
from google.cloud.storage import Client
def make_signed_upload_url(
bucket: str,
blob: str,
*,
exp: Optional[timedelta] = None,
content_type="application/octet-stream",
min_size=1,
max_size=int(1e6)
):
"""
Compute a GCS signed upload URL without needing a private key file.
Can only be called when a service account is used as the application
default credentials, and when that service account has the proper IAM
roles, like `roles/storage.objectCreator` for the bucket, and
`roles/iam.serviceAccountTokenCreator`.
Source: https://stackoverflow.com/a/64245028
Parameters
----------
bucket : str
Name of the GCS bucket the signed URL will reference.
blob : str
Name of the GCS blob (in `bucket`) the signed URL will reference.
exp : timedelta, optional
Time from now when the signed url will expire.
content_type : str, optional
The required mime type of the data that is uploaded to the generated
signed url.
min_size : int, optional
The minimum size the uploaded file can be, in bytes (inclusive).
If the file is smaller than this, GCS will return a 400 code on upload.
max_size : int, optional
The maximum size the uploaded file can be, in bytes (inclusive).
If the file is larger than this, GCS will return a 400 code on upload.
"""
if exp is None:
exp = timedelta(hours=1)
credentials, project_id = auth.default()
if credentials.token is None:
# Perform a refresh request to populate the access token of the
# current credentials.
credentials.refresh(requests.Request())
client = Client()
bucket = client.get_bucket(bucket)
blob = bucket.blob(blob)
return blob.generate_signed_url(
version="v4",
expiration=exp,
service_account_email=credentials.service_account_email,
access_token=credentials.token,
method="PUT",
content_type=content_type,
headers={"X-Goog-Content-Length-Range": f"{min_size},{max_size}"}
)
地形
インフラを持たない雲をコードとして行う堅牢な方法はないTerraform あなたのクラウドリソースを管理するための最適なツールです.
このデザインを展開するための地形図です.
# Resources to handle big data files (>32 Mb)
# These files are uploaded to a special bucket with notifications
provider "google-beta" {
project = <your GCP project name>
}
data "google_project" "default" {
provider = google-beta
}
resource "google_storage_bucket" "bigframes_bucket" {
project = <your GCP project name>
name = "upload-big-files"
location = "EU"
cors {
origin = ["*"]
method = ["*"]
response_header = [
"Content-Type",
"Access-Control-Allow-Origin",
"X-Goog-Content-Length-Range"
]
max_age_seconds = 3600
}
}
resource "google_service_account" "default" {
provider = google-beta
account_id = "sa-webservice"
}
resource "google_storage_bucket_iam_member" "bigframes_admin" {
bucket = google_storage_bucket.bigframes_bucket.name
role = "roles/storage.admin"
member = "serviceAccount:${google_service_account.default.email}"
}
# required to generate a signed url
resource "google_service_account_iam_member" "tokencreator" {
provider = google-beta
service_account_id = google_service_account.default.name
role = "roles/iam.serviceAccountTokenCreator"
member = "serviceAccount:${google_service_account.default.email}"
}
# upload topic for notifications
resource "google_pubsub_topic" "bigframes_topic" {
provider = google-beta
name = "topic-bigframes"
}
# upload deadletter topic for failed notifications
resource "google_pubsub_topic" "bigframes_topic_deadletter" {
provider = google-beta
name = "topic-bigframesdeadletter"
}
# add frame upload notifications on the bucket
resource "google_storage_notification" "bigframes_notification" {
provider = google-beta
bucket = google_storage_bucket.bigframes_bucket.name
payload_format = "JSON_API_V1"
topic = google_pubsub_topic.bigframes_topic.id
event_types = ["OBJECT_FINALIZE"]
depends_on = [google_pubsub_topic_iam_binding.bigframes_binding]
}
# required for storage notifications
# seriously, Google, this should be by default !
resource "google_pubsub_topic_iam_binding" "bigframes_binding" {
topic = google_pubsub_topic.bigframes_topic.id
role = "roles/pubsub.publisher"
members = ["serviceAccount:service-${data.google_project.default.number}@gs-project-accounts.iam.gserviceaccount.com"]
}
# frame upload main sub
resource "google_pubsub_subscription" "bigframes_sub" {
provider = google-beta
name = "sub-bigframes"
topic = google_pubsub_topic.bigframes_topic.id
push_config {
push_endpoint = <URL where pushed notification are POST-ed>
}
dead_letter_policy {
dead_letter_topic = google_pubsub_topic.bigframes_topic_deadletter.id
}
}
# frame upload deadletter subscription
resource "google_pubsub_subscription" "bigframes_sub_deadletter" {
provider = google-beta
name = "sub-bigframesdeadletter"
topic = google_pubsub_topic.bigframes_topic_deadletter.id
ack_deadline_seconds = 600
push_config {
push_endpoint = <URL where pushed notification are POST-ed>
}
}
ジャストterraform deploy
それ!ハウツーとスタイル
つの最終的なgotcha:署名されたURLでクラウドストレージにアップロードするには、
PUT
リクエストX-Goog-Content-Length-Range: <min size>,<max size>
どこmin size
and max size
マッチmin_size
and max_size
のmake_signed_upload_url()
上記のメソッド.結論
このデザインを経験しましたか.どうやってそれを改善するの?コメントを教えてください.
デザインスキーマExcalidraw とGCPのアイコンライブラリ
カバー写真joel herzog on Unsplash
Reference
この問題について(クラウド・ランの32 MB要求制限を克服する方法), 我々は、より多くの情報をここで見つけました https://dev.to/stack-labs/how-to-overcome-cloud-runs-32mb-request-limit-190jテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol