Pic-a-day: Lab 6 — Orchestration with Workflows

۱. مرور کلی

در آزمایش‌های قبلی، شما یک نسخه رویداد-محور از برنامه Pic-a-daily ساختید که از یک تابع ابری فعال‌شده توسط Google Cloud Storage برای سرویس تحلیل تصویر، یک کانتینر Cloud Run فعال‌شده توسط GCS از طریق Pub/Sub برای سرویس Thumbnail و Eventarc برای فعال‌سازی سرویس Image Garbage Collector در Cloud Run استفاده می‌کرد. همچنین یک سرویس کلاژ فعال‌شده توسط Cloud Scheduler نیز وجود داشت:

d93345bfc235f81e.png

در این آزمایش، شما یک نسخه هماهنگ از برنامه ایجاد خواهید کرد. به جای انواع مختلف رویدادهای جاری در سیستم، از Workflows برای هماهنگ‌سازی و فراخوانی سرویس‌ها به شرح زیر استفاده خواهید کرد:

b763efcbf5589747.png

آنچه یاد خواهید گرفت

  • موتور برنامه
  • فروشگاه ابری فایر استور
  • توابع ابری
  • اجرای ابری
  • گردش‌های کاری

۲. تنظیمات و الزامات

تنظیم محیط خودتنظیم

  1. وارد Cloud Console شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. (اگر از قبل حساب Gmail یا Google Workspace ندارید، باید یکی ایجاد کنید .)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

شناسه پروژه را به خاطر بسپارید، یک نام منحصر به فرد در تمام پروژه‌های Google Cloud (نام بالا قبلاً گرفته شده و برای شما کار نخواهد کرد، متاسفیم!). بعداً در این آزمایشگاه کد به آن PROJECT_ID گفته خواهد شد.

  1. در مرحله بعد، برای استفاده از منابع گوگل کلود، باید پرداخت را در Cloud Console فعال کنید .

اجرای این آزمایشگاه کد، اگر اصلاً هزینه‌ای نداشته باشد، نباید هزینه زیادی داشته باشد. حتماً دستورالعمل‌های بخش «پاکسازی» را که به شما نحوه خاموش کردن منابع را آموزش می‌دهد، دنبال کنید تا پس از این آموزش، متحمل هزینه نشوید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.

شروع پوسته ابری

اگرچه می‌توان از راه دور و از طریق لپ‌تاپ، گوگل کلود را مدیریت کرد، اما در این آزمایشگاه کد، از گوگل کلود شل ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهید کرد.

از کنسول GCP روی آیکون Cloud Shell در نوار ابزار بالا سمت راست کلیک کنید:

bce75f34b2c53987.png

آماده‌سازی و اتصال به محیط فقط چند لحظه طول می‌کشد. وقتی تمام شد، باید چیزی شبیه به این را ببینید:

f6ef2b5f13479f3a.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز شماست. این ماشین یک دایرکتوری خانگی دائمی ۵ گیگابایتی ارائه می‌دهد و روی فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود می‌بخشد. تمام کارهای شما در این آزمایشگاه را می‌توان به سادگی با یک مرورگر انجام داد.

۳. مقدمه‌ای بر گردش‌های کاری

90fcd42d556e310e.jpeg

شما می‌توانید از Workflowها برای ایجاد گردش‌های کاری بدون سرور استفاده کنید که مجموعه‌ای از وظایف بدون سرور را به ترتیبی که شما تعریف می‌کنید، به هم پیوند می‌دهند. می‌توانید قدرت APIهای Google Cloud، محصولات بدون سرور مانند Cloud Functions و Cloud Run و فراخوانی‌های APIهای خارجی را برای ایجاد برنامه‌های بدون سرور انعطاف‌پذیر ترکیب کنید.

همانطور که از یک هماهنگ‌کننده انتظار می‌رود، Workflows به شما امکان می‌دهد جریان منطق کسب‌وکار خود را در یک زبان تعریف گردش کار مبتنی بر YAML/JSON تعریف کنید و یک API اجرای گردش‌های کار و رابط کاربری گردش‌های کار را برای راه‌اندازی آن جریان‌ها فراهم می‌کند.

این نرم‌افزار با ویژگی‌های داخلی و قابل تنظیم زیر، چیزی بیش از یک هماهنگ‌کننده‌ی صرف است:

  • قابلیت انعطاف‌پذیری در تلاش مجدد و مدیریت خطا بین مراحل برای اجرای مطمئن مراحل.
  • تجزیه JSON و ارسال متغیر بین مراحل برای جلوگیری از کد چسبی.
  • فرمول‌های بیان برای تصمیم‌گیری‌ها، اجرای مراحل شرطی را امکان‌پذیر می‌کنند.
  • زیرگردش‌های کاری برای گردش‌های کاری ماژولار و قابل استفاده مجدد.
  • پشتیبانی از سرویس‌های خارجی، امکان هماهنگ‌سازی سرویس‌هایی فراتر از Google Cloud را فراهم می‌کند.
  • پشتیبانی از احراز هویت برای Google Cloud و سرویس‌های خارجی برای اجرای امن مراحل.
  • اتصال به سرویس‌های ابری گوگل مانند Pub/Sub، Firestore، Tasks و Secret Manager برای یکپارچه‌سازی آسان‌تر.

ناگفته نماند، Workflows یک محصول کاملاً مدیریت‌شده بدون سرور است. هیچ سروری برای پیکربندی یا مقیاس‌بندی وجود ندارد و شما فقط برای آنچه استفاده می‌کنید هزینه پرداخت می‌کنید.

۴. فعال کردن APIها

در این آزمایشگاه، شما سرویس‌های Cloud Functions و Cloud Run را با Workflows متصل خواهید کرد. همچنین از App Engine، Cloud Build، Vision API و سایر سرویس‌ها استفاده خواهید کرد.

در Cloud Shell، مطمئن شوید که تمام سرویس‌های لازم فعال هستند:

gcloud services enable \
  appengine.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  compute.googleapis.com \
  firestore.googleapis.com \
  run.googleapis.com \
  vision.googleapis.com \
  workflows.googleapis.com \

پس از مدتی، باید ببینید که عملیات با موفقیت به پایان رسیده است:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

۵. کد را دریافت کنید

اگر کد را در آزمایشگاه‌های کد قبلی دریافت نکرده‌اید، آن را دریافت کنید:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

ساختار پوشه‌ای زیر را خواهید داشت که برای این تمرین مرتبط است:

frontend
 |
workflows
 |
 ├── functions
 ├── |── trigger-workflow
 ├── |── vision-data-transform
 ├── services
 ├── |── collage
 ├── |── thumbnails
 ├── workflows.yaml

اینم پوشه‌های مربوطه:

  • frontend شامل بخش frontend مربوط به App Engine است که از تمرین چهارم دوباره از آن استفاده خواهیم کرد.
  • functions شامل توابع ابری ایجاد شده برای گردش کار است.
  • services شامل سرویس‌های Cloud Run اصلاح‌شده برای گردش کار هستند.
  • workflows.yaml فایل تعریف گردش کار است.

۶. گردش‌های کاری YAML را بررسی کنید

فایل workflows.yaml، گردش کار را در یک سری مراحل تعریف می‌کند. بیایید برای درک بهتر آن را بررسی کنیم.

در ابتدای گردش کار، پارامترهایی وجود دارند که ارسال می‌شوند. این پارامترها توسط دو تابع ابری که گردش‌های کاری را فعال می‌کنند، ارسال می‌شوند. بعداً به این توابع خواهیم پرداخت، اما نحوه شروع گردش‌های کاری به این صورت است:

d44a5e18aa9d4660.png

In YAML, you can see that these parameters are assigned to variables in the init step such as the file and bucket names triggering the event, and URLs of some Cloud Functions and Cloud Run services that Workflows will call:

main:
  params: [args]
  steps:
    - init:
        assign:
          - file: ${args.file}
          - bucket: ${args.bucket}
          - gsUri: ${"gs://" + bucket + "/" + file}
          - projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
          - urls: ${args.urls}

در مرحله بعد، Workflowها نوع رویداد را بررسی می‌کنند. دو نوع رویداد پشتیبانی می‌شوند: object.finalize (زمانی که یک فایل در فضای ذخیره‌سازی ابری ذخیره می‌شود، منتشر می‌شود) و object.delete (زمانی که یک فایل حذف می‌شود، منتشر می‌شود). هر چیز دیگری باعث ایجاد خطای event not supported می‌شود.

dd1f450983655619.png

این مرحله در تعریف گردش کار YAML است که در آن نوع رویداد ذخیره‌سازی فایل را بررسی می‌کنیم:

    - eventTypeSwitch:
        switch:
            - condition: ${args.eventType == "google.storage.object.finalize"}
              next: imageAnalysisCall
            - condition: ${args.eventType == "google.storage.object.delete"}
              next: pictureGarbageCollectionGCS
    - eventTypeNotSupported:
        raise: ${"eventType " + args.eventType + " is not supported"}
        next: end

توجه کنید که چگونه Workflows از دستورات switch و مدیریت استثنا پشتیبانی می‌کند، با دستور switch و شرایط مختلف آن، و دستور raise برای ایجاد خطا زمانی که رویداد تشخیص داده نمی‌شود.

در مرحله بعد، بیایید نگاهی به imageAnalysisCall بیندازیم. این یک سری فراخوانی از Workflows برای فراخوانی Vision API جهت تجزیه و تحلیل تصویر، تبدیل داده‌های پاسخ Vision API برای مرتب‌سازی برچسب‌های موارد شناسایی شده در تصویر، انتخاب رنگ‌های غالب، بررسی ایمن بودن نمایش تصویر و سپس ذخیره ابرداده در Cloud Firestore است.

توجه داشته باشید که همه چیز در Workflows انجام می‌شود به جز توابع Vision Transform Cloud (که بعداً آنها را مستقر خواهیم کرد):

ca2ad16b9cbb436.png

مراحل در YAML به این صورت است:

    - imageAnalysisCall:
        call: http.post
        args:
          url: https://vision.googleapis.com/v1/images:annotate
          headers:
            Content-Type: application/json
          auth:
            type: OAuth2
          body:
            requests:
            - image:
                source:
                  gcsImageUri: ${gsUri}
              features:
              - type: LABEL_DETECTION
              - type: SAFE_SEARCH_DETECTION
              - type: IMAGE_PROPERTIES
        result: imageAnalysisResponse
    - transformImageAnalysisData:
        call: http.post
        args:
          url: ${urls.VISION_DATA_TRANSFORM_URL}
          auth:
            type: OIDC
          body: ${imageAnalysisResponse.body}
        result: imageMetadata
    - checkSafety:
        switch:
          - condition: ${imageMetadata.body.safe == true}
            next: storeMetadata
        next: end
    - storeMetadata:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
          auth:
            type: OAuth2
          method: PATCH
          body:
            name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
            fields:
              color:
                stringValue: ${imageMetadata.body.color}
              created:
                timestampValue: ${imageMetadata.body.created}
              labels:
                arrayValue:
                  values: ${imageMetadata.body.labels}
        result: storeMetadataResponse

پس از تجزیه و تحلیل تصویر، دو مرحله بعدی ایجاد تصویر بندانگشتی از تصویر و یک کلاژ از جدیدترین تصاویر است. این کار با استقرار دو سرویس Cloud Run و فراخوانی آنها از مراحل thumbnailCall و collageCall انجام می‌شود:

76f9179323c3144.png

مراحل در YAML:

   - thumbnailCall:
        call: http.post
        args:
          url: ${urls.THUMBNAILS_URL}
          auth:
            type: OIDC
          body:
              gcsImageUri: ${gsUri}
        result: thumbnailResponse
    - collageCall:
        call: http.get
        args:
          url: ${urls.COLLAGE_URL}
          auth:
            type: OIDC
        result: collageResponse

این شاخه از اجرا با برگرداندن کدهای وضعیت از هر سرویس در مرحله finalizeCompleted به پایان می‌رسد:

    - finalizeCompleted:
        return:
          imageAnalysis: ${imageAnalysisResponse.code}
          storeMetadata: ${storeMetadataResponse.code}
          thumbnail: ${thumbnailResponse.code}
          collage: ${collageResponse.code}

شاخه‌ی دیگر اجرا زمانی است که یک فایل از سطل ذخیره‌سازی اصلی که حاوی نسخه‌های با وضوح بالای تصاویر است، حذف می‌شود. در این شاخه، می‌خواهیم تصویر کوچک تصویر را در سطل حاوی تصاویر کوچک حذف کنیم و فراداده‌های آن را از Firestore حذف کنیم. هر دوی این‌ها با فراخوانی‌های HTTP از Workflows انجام می‌شوند:

f172379274dcb3c2.png

مراحل در YAML:

    - pictureGarbageCollectionGCS:
        try:
          call: http.request
          args:
            url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
            auth:
              type: OAuth2
            method: DELETE
          result: gcsDeletionResult
        except:
          as: e
          steps:
              - dummyResultInOutVar:
                  assign:
                      - gcsDeletionResult:
                          code: 200
                          body: "Workaround for empty body response"
    - pictureGarbageCollectionFirestore:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
          auth:
            type: OAuth2
          method: DELETE
        result: firestoreDeletionResult

شاخه‌ی حذف با برگرداندن نتایج/کدهای هر مرحله به پایان می‌رسد:

    - deleteCompleted:
        return:
          gcsDeletion: ${gcsDeletionResult}
          firestoreDeletion: ${firestoreDeletionResult.code}

در مراحل بعدی، تمام وابستگی‌های خارجی گردش‌های کاری را ایجاد خواهیم کرد: سطل‌ها، توابع ابری، سرویس‌های Cloud Run و پایگاه داده Firestore.

۷. سطل‌ها را ایجاد کنید

شما به دو سطل برای تصاویر نیاز دارید: یکی برای ذخیره تصاویر اصلی با وضوح بالا و یکی برای ذخیره تصاویر کوچک.

با استفاده از ابزار gsutil یک سطل عمومی منطقه‌ای (در این مورد در اروپا) با دسترسی یکسان برای کاربران جهت آپلود تصاویر ایجاد کنید:

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}

یک سطل منطقه‌ای عمومی دیگر برای تصاویر کوچک ایجاد کنید:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}

با مراجعه به بخش ذخیره‌سازی ابری در کنسول ابری، می‌توانید دوباره بررسی کنید که سطل‌ها ایجاد شده و عمومی هستند:

۱۵۰۶۳۹۳۶edd72f06.png

۸. تبدیل داده‌های بینایی (عملکرد ابری)

Workflows.yaml با مراحل init ، eventTypeSwitch و eventTypeNotSupported شروع می‌شود. این مراحل تضمین می‌کنند که رویدادهای دریافتی از bucketها به مراحل صحیح هدایت شوند.

برای رویداد object.finalize ، مرحله imageAnalysisCall فراخوانی به Vision API برای استخراج فراداده‌های تصویر ایجاد شده انجام می‌دهد. همه این مراحل در Workflows انجام می‌شوند:

daaed43a22d2b0d3.png

در مرحله بعد، قبل از اینکه بتوانیم داده‌های برگردانده شده از Vision API را در Firestore ذخیره کنیم، باید آنها را تبدیل کنیم. به طور خاص، باید:

  • برچسب‌های برگردانده شده برای تصویر را فهرست کنید.
  • رنگ غالب تصویر را بازیابی کنید.
  • مشخص کنید که آیا تصویر ایمن است یا خیر.

این کار به صورت کد در یک تابع ابری انجام می‌شود و Workflows به سادگی این تابع را فراخوانی می‌کند:

5e120e70c67779cd.png

کد را کاوش کنید

تابع ابری vision-data-transform نام دارد. می‌توانید کد کامل آن را در index.js بررسی کنید. همانطور که می‌بینید، تنها هدف این تابع انجام تبدیل JSON به JSON است تا بتوان فراداده‌های تصویر را به راحتی در Firestore ذخیره کرد.

توابع را به فضای ابری منتقل کنید

به پوشه بروید:

cd workflows/functions/vision-data-transform/nodejs

منطقه مورد نظر خود را تنظیم کنید:

export REGION=europe-west1
gcloud config set functions/region ${REGION}

تابع را با موارد زیر مستقر کنید:

export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=vision_data_transform \
  --trigger-http \
  --allow-unauthenticated

پس از استقرار تابع، مرحله transformImageAnalysisData در Workflows قادر خواهد بود این تابع را برای انجام تبدیل داده‌های Vision API فراخوانی کند.

۹. آماده‌سازی پایگاه داده

مرحله بعدی در گردش‌های کاری، بررسی ایمنی تصویر از داده‌های تصویر و سپس ذخیره اطلاعات مربوط به تصویر برگردانده شده توسط Vision API در پایگاه داده Cloud Firestore است، یک پایگاه داده سند NoSQL سریع، کاملاً مدیریت‌شده، بدون سرور و ابری:

6624c616bc7cd97f.png

هر دوی این موارد در Workflows انجام می‌شوند، اما برای ذخیره‌سازی فراداده‌ها باید پایگاه داده Firestore را ایجاد کنید.

ابتدا، یک برنامه App engine در منطقه‌ای که می‌خواهید پایگاه داده Firestore در آن قرار گیرد (یک الزام برای Firestore) ایجاد کنید:

export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}

در مرحله بعد، پایگاه داده Firestore را در همان منطقه ایجاد کنید:

gcloud firestore databases create --region=${REGION_FIRESTORE}

این اسناد به صورت برنامه‌نویسی شده در مجموعه ما ایجاد می‌شوند و شامل ۴ فیلد خواهند بود:

  • نام (رشته): نام فایل تصویر آپلود شده که کلید سند نیز هست.
  • برچسب‌ها (آرایه‌ای از رشته‌ها): برچسب‌های اقلام شناسایی‌شده توسط Vision API
  • رنگ (رشته): کد رنگ هگزادسیمال رنگ غالب (مثلاً #ab12ef)
  • ایجاد شده (تاریخ): مهر زمانی ذخیره شدن فراداده‌های این تصویر
  • تصویر بندانگشتی (boolean): یک فیلد اختیاری که در صورت ایجاد تصویر بندانگشتی برای این تصویر، وجود خواهد داشت و مقدار آن true خواهد بود.

از آنجایی که ما در Firestore به دنبال تصاویری خواهیم گشت که تصویر بندانگشتی (thumbnail) آنها موجود باشد و آنها را بر اساس تاریخ ایجاد مرتب کنیم، باید یک فهرست جستجو ایجاد کنیم. می‌توانید این فهرست را با دستور زیر ایجاد کنید:

gcloud firestore indexes composite create --collection-group=pictures \
  --field-config field-path=thumbnail,order=descending \
  --field-config field-path=created,order=descending

توجه داشته باشید که ایجاد ایندکس می‌تواند تا 10 دقیقه یا بیشتر طول بکشد.

پس از ایجاد ایندکس، می‌توانید آن را در Cloud Console مشاهده کنید:

43af1f5103bf423.png

مرحله‌ی storeMetadata در گردش کار، اکنون می‌تواند متادیتای تصویر را در Firestore ذخیره کند.

۱۰. سرویس تصویر بندانگشتی (Cloud Run)

مرحله بعدی در این زنجیره، ایجاد یک تصویر بندانگشتی از یک تصویر است. این کار به صورت کد در یک سرویس Cloud Run انجام می‌شود و Workflows این سرویس را در مرحله thumbnailCall فراخوانی می‌کند:

84d987647f082b53.png

کد را کاوش کنید

سرویس Cloud Run، thumbnails نام دارد. می‌توانید کد کامل آن را در index.js بررسی کنید.

ساخت و انتشار تصویر کانتینر

Cloud Run کانتینرها را اجرا می‌کند، اما ابتدا باید تصویر کانتینر (تعریف شده در Dockerfile ) را بسازید. Google Cloud Build می‌تواند برای ساخت تصاویر کانتینر و سپس میزبانی در Google Container Registry استفاده شود.

به پوشه بروید:

cd workflows/services/thumbnails/nodejs

ساخت:

export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

بعد از یک یا دو دقیقه، ساخت باید با موفقیت انجام شود و کانتینر در رجیستری کانتینر گوگل مستقر شود.

استقرار در Cloud Run

برخی از متغیرها و پیکربندی‌های مورد نیاز را تنظیم کنید:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

با دستور زیر مستقر کنید:

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

پس از استقرار سرویس، مرحله thumbnailCall در Workflows قادر به فراخوانی این سرویس خواهد بود.

۱۱. سرویس کلاژ (Cloud Run)

مرحله بعدی در این زنجیره، ایجاد یک کلاژ از جدیدترین تصاویر است. این کار به صورت کد در سرویس Cloud Run انجام می‌شود و Workflows این سرویس را در مرحله collageCall فراخوانی می‌کند:

591e36149066e1ba.png

کد را کاوش کنید

سرویس Cloud Run، collage نام دارد. می‌توانید کد کامل آن را در index.js بررسی کنید.

ساخت و انتشار تصویر کانتینر

Cloud Run کانتینرها را اجرا می‌کند، اما ابتدا باید تصویر کانتینر (تعریف شده در Dockerfile ) را بسازید. Google Cloud Build می‌تواند برای ساخت تصاویر کانتینر و سپس میزبانی در Google Container Registry استفاده شود.

به پوشه بروید:

cd services/collage/nodejs

ساخت:

export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

بعد از یک یا دو دقیقه، ساخت باید با موفقیت انجام شود و کانتینر در رجیستری کانتینر گوگل مستقر شود.

استقرار در Cloud Run

برخی از متغیرها و پیکربندی‌های مورد نیاز را تنظیم کنید:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

استقرار:

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

پس از استقرار سرویس، می‌توانید بررسی کنید که هر دو سرویس در بخش Cloud Run از Cloud Console اجرا می‌شوند و در مرحله collageCall Workflows می‌توانید این سرویس را فراخوانی کنید:

3ae9873f4cbbf423.png

۱۲. استقرار گردش‌های کاری

ما تمام وابستگی‌های خارجی Workflows را مستقر کردیم. تمام مراحل باقی‌مانده ( finalizeCompleted ، pictureGarbageCollectionGCS ، pictureGarbageCollectionFirestore ، deleteCompleted ) می‌توانند توسط خود Workflows تکمیل شوند.

وقت آن است که Workflowها را مستقر کنیم!

به پوشه‌ای که حاوی فایل workflows.yaml است بروید و آن را با دستور زیر مستقر کنید:

export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
  --source=workflows.yaml \
  --location=${WORKFLOW_REGION}

ظرف چند ثانیه، گردش کار باید اجرا شود و می‌توانید آن را در بخش گردش‌های کاری Cloud Console مشاهده کنید:

94a720149e5df9c5.png

در صورت تمایل می‌توانید روی گردش کار کلیک کرده و آن را ویرایش کنید. در حین ویرایش، یک نمایش بصری زیبا از گردش کار دریافت خواهید کرد:

۵۵۴۴۱b۱۵۸f۶۰۲۷f۳.png

همچنین می‌توانید Workflow را از Cloud Console به صورت دستی با پارامترهای مناسب اجرا کنید. در عوض، ما آن را به صورت خودکار در پاسخ به رویدادهای Cloud Storage در مرحله بعدی اجرا خواهیم کرد.

۱۳. محرک‌های گردش کار (توابع ابری)

گردش کار مستقر و آماده است. اکنون، باید گردش‌های کاری را هنگامی که یک فایل در یک مخزن ذخیره‌سازی ابری ایجاد یا حذف می‌شود، فعال کنیم. این رویدادها به ترتیب storage.object.finalize و storage.object.delete هستند.

گردش‌های کاری دارای APIها و کتابخانه‌های کلاینت برای ایجاد، مدیریت و اجرای گردش‌های کاری هستند که می‌توانید از آنها استفاده کنید. در این حالت، شما از API اجرای گردش‌های کاری و به طور خاص‌تر از کتابخانه کلاینت Node.js آن برای راه‌اندازی گردش کار استفاده خواهید کرد.

شما گردش‌های کاری را از تابع ابری فعال می‌کنید که به رویدادهای ذخیره‌سازی ابری گوش می‌دهند. از آنجایی که یک تابع ابری فقط می‌تواند به یک نوع رویداد گوش دهد، شما دو تابع ابری را برای گوش دادن به رویدادهای ایجاد و حذف مستقر خواهید کرد:

c4d79646de729e4.png

کد را کاوش کنید

تابع ابری trigger-workflow نام دارد. می‌توانید کد کامل آن را در index.js بررسی کنید.

توابع را به فضای ابری منتقل کنید

به پوشه بروید:

cd workflows/functions/trigger-workflow/nodejs

برخی از متغیرها و پیکربندی‌های مورد نیاز را تنظیم کنید:

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}

تابعی را که به رویدادهای نهایی پاسخ می‌دهد، مستقر کنید:

export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.finalize \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

تابع دوم را که به رویدادهای حذف پاسخ می‌دهد، پیاده‌سازی کنید:

export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.delete \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

وقتی استقرار کامل شد، می‌توانید هر دو عملکرد را در Cloud Console مشاهده کنید:

7d60c8b7851f39f5.png

۱۴. فرانت‌اند (موتور برنامه)

در این مرحله، شما یک رابط کاربری وب در Google App Engine از Pic-a-daily ایجاد می‌کنید: تمرین ۴ - یک رابط کاربری وب ایجاد کنید که به کاربران امکان آپلود تصاویر از برنامه وب و همچنین مرور تصاویر آپلود شده و تصاویر کوچک آنها را می‌دهد.

۲۲۳fb۲۲۸۱۶۱۴d۰۵۳.png

می‌توانید اطلاعات بیشتری در مورد App Engine کسب کنید و توضیحات کد را در Pic-a-daily: آزمایشگاه ۴ - ایجاد یک رابط کاربری وب بخوانید.

کد را کاوش کنید

برنامه‌ی App Engine، frontend نام دارد. می‌توانید کد کامل آن را در index.js بررسی کنید.

استقرار در موتور برنامه

به پوشه بروید:

cd frontend

منطقه مورد نظر خود را تنظیم کنید و همچنین GOOGLE_CLOUD_PROJECT را در app.yaml با شناسه پروژه واقعی خود جایگزین کنید:

export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml

استقرار:

gcloud app deploy app.yaml -q

بعد از یک یا دو دقیقه، به شما گفته می‌شود که برنامه در حال ارائه ترافیک است:

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 8 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com]
You can stream logs from the command line by running:
  $ gcloud app logs tail -s default
To view your application in the web browser run:
  $ gcloud app browse

همچنین می‌توانید از بخش App Engine در Cloud Console دیدن کنید تا ببینید آیا برنامه مستقر شده است و ویژگی‌های App Engine مانند نسخه‌بندی و تقسیم ترافیک را بررسی کنید:

f4bd5f4de028b83.png

۱۵. گردش‌های کاری را آزمایش کنید

برای آزمایش، به آدرس پیش‌فرض موتور برنامه ( https://<YOUR_PROJECT_ID>.appspot.com/ ) بروید و باید رابط کاربری frontend را در حال اجرا ببینید!

1649ac060441099.png

یک عکس آپلود کنید. این کار باید گردش‌های کاری را فعال کند و شما می‌توانید اجرای گردش کار را در حالت Active در Cloud Console مشاهده کنید:

b5a2a3d7a2bc094.png

پس از اتمام گردش‌های کاری، می‌توانید روی شناسه اجرا کلیک کنید و خروجی سرویس‌های مختلف را مشاهده کنید:

8959df5098c21548.png

۳ عکس دیگر آپلود کنید. همچنین باید تصویر کوچک و کلاژ تصاویر را در Cloud Storage buckets ببینید و ظاهر App Engine به‌روزرسانی شود:

d90c786ff664a5dc.png

۱۶. تمیز کردن (اختیاری)

اگر قصد ندارید برنامه را نگه دارید، می‌توانید با حذف کل پروژه، منابع را پاکسازی کنید تا در هزینه‌ها صرفه‌جویی کنید و در کل یک شهروند ابری خوب باشید:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

۱۷. تبریک می‌گویم!

شما یک نسخه هماهنگ از برنامه را با استفاده از Workflows برای هماهنگ‌سازی و فراخوانی سرویس‌ها ایجاد کردید.

آنچه ما پوشش داده‌ایم

  • موتور برنامه
  • فروشگاه ابری فایر استور
  • توابع ابری
  • اجرای ابری
  • گردش‌های کاری