รูปภาพรายวัน: ห้องปฏิบัติการ 6 - การเรียบเรียงด้วยเวิร์กโฟลว์

1. ภาพรวม

ในแล็บก่อนหน้านี้ คุณได้สร้างแอป Pic-a-daily เวอร์ชันที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งใช้ Cloud Function ที่ทริกเกอร์โดย Google Cloud Storage สำหรับบริการวิเคราะห์รูปภาพ คอนเทนเนอร์ Cloud Run ที่ทริกเกอร์โดย GCS ผ่าน Pub/Sub สำหรับบริการภาพขนาดย่อ และ Eventarc เพื่อทริกเกอร์บริการ Image Garbage Collector ใน Cloud Run นอกจากนี้ ยังมีบริการ Collage ที่ทริกเกอร์โดย Cloud Scheduler ด้วย

d93345bfc235f81e.png

ในแล็บนี้ คุณจะสร้างแอปเวอร์ชันที่จัดระเบียบแล้ว แทนที่จะใช้เหตุการณ์ประเภทต่างๆ ที่ไหลผ่านระบบ คุณจะใช้เวิร์กโฟลว์เพื่อจัดระเบียบและเรียกใช้บริการดังนี้

b763efcbf5589747.png

สิ่งที่คุณจะได้เรียนรู้

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • เวิร์กโฟลว์

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ (หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

โปรดจดจำรหัสโปรเจ็กต์ ซึ่งเป็นชื่อที่ไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมด (ชื่อด้านบนมีผู้ใช้แล้วและจะใช้ไม่ได้ ขออภัย) ซึ่งจะเรียกว่า PROJECT_ID ในภายหลังใน Codelab นี้

  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร Google Cloud

การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีเลย โปรดทำตามวิธีการในส่วน "การล้างข้อมูล" ซึ่งจะแนะนำวิธีปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

เริ่มต้น Cloud Shell

แม้ว่าคุณจะใช้งาน Google Cloud จากระยะไกลจากแล็ปท็อปได้ แต่ใน Codelab นี้คุณจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์

จาก GCP Console ให้คลิกไอคอน Cloud Shell ในแถบเครื่องมือด้านขวาบน

bce75f34b2c53987.png

การจัดสรรและเชื่อมต่อกับสภาพแวดล้อมจะใช้เวลาเพียงไม่กี่นาที เมื่อเสร็จแล้ว คุณควรเห็นข้อความคล้ายกับตัวอย่างต่อไปนี้

f6ef2b5f13479f3a.png

เครื่องเสมือนนี้มาพร้อมเครื่องมือพัฒนาซอฟต์แวร์ทั้งหมดที่คุณต้องการ โดยมีไดเรกทอรีหลักแบบถาวรขนาด 5 GB และทำงานบน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานทั้งหมดในห้องทดลองนี้ได้โดยใช้เพียงเบราว์เซอร์

3. ข้อมูลเบื้องต้นเกี่ยวกับเวิร์กโฟลว์

90fcd42d556e310e.jpeg

คุณใช้ Workflows เพื่อสร้างเวิร์กโฟลว์แบบไร้เซิร์ฟเวอร์ที่ลิงก์ชุดงานแบบไร้เซิร์ฟเวอร์เข้าด้วยกันตามลำดับที่คุณกำหนดได้ คุณสามารถผสานประสิทธิภาพของ API ของ Google Cloud, ผลิตภัณฑ์แบบ Serverless เช่น Cloud Functions และ Cloud Run รวมถึงการเรียกใช้ API ภายนอกเพื่อสร้างแอปพลิเคชันแบบ Serverless ที่ยืดหยุ่น

ดังที่คาดไว้จากเครื่องมือจัดระเบียบ เวิร์กโฟลว์ช่วยให้คุณกำหนดโฟลว์ของตรรกะทางธุรกิจในภาษาคำจำกัดความของเวิร์กโฟลว์ที่อิงตาม YAML/JSON และมี Workflows Execution API และ UI ของเวิร์กโฟลว์เพื่อทริกเกอร์โฟลว์เหล่านั้น

โดยมีฟีเจอร์ในตัวและกำหนดค่าได้ดังนี้

  • การลองใหม่ที่ยืดหยุ่นและการจัดการข้อผิดพลาดระหว่างขั้นตอนเพื่อให้การดำเนินการขั้นตอนต่างๆ เป็นไปอย่างน่าเชื่อถือ
  • การแยกวิเคราะห์ JSON และการส่งตัวแปรระหว่างขั้นตอนเพื่อหลีกเลี่ยงโค้ดกาว
  • สูตรนิพจน์สำหรับการตัดสินใจช่วยให้การดำเนินการตามขั้นตอนมีเงื่อนไข
  • เวิร์กโฟลว์ย่อยสำหรับเวิร์กโฟลว์แบบแยกส่วนและนำกลับมาใช้ใหม่ได้
  • การรองรับบริการภายนอกช่วยให้สามารถจัดระเบียบบริการนอก Google Cloud ได้
  • รองรับการตรวจสอบสิทธิ์สำหรับ Google Cloud และบริการภายนอกเพื่อการดำเนินการขั้นตอนที่ปลอดภัย
  • เครื่องมือเชื่อมต่อกับบริการของ Google Cloud เช่น Pub/Sub, Firestore, Tasks, Secret Manager เพื่อการผสานรวมที่ง่ายขึ้น

นอกจากนี้ เวิร์กโฟลว์ยังเป็นผลิตภัณฑ์แบบ Serverless ที่มีการจัดการครบวงจรอีกด้วย ไม่ต้องกำหนดค่าหรือปรับขนาดเซิร์ฟเวอร์ และคุณจะจ่ายเฉพาะที่ใช้ไปเท่านั้น

4. เปิดใช้ API

ในแล็บนี้ คุณจะได้เชื่อมต่อบริการ Cloud Functions และ Cloud Run กับเวิร์กโฟลว์ นอกจากนี้ คุณยังจะได้ใช้ 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.

5. รับโค้ด

รับรหัสหากคุณยังไม่มีในโค้ดแล็บก่อนหน้า

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

คุณจะมีโครงสร้างโฟลเดอร์ต่อไปนี้ที่เกี่ยวข้องกับแล็บนี้

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

โฟลเดอร์ที่เกี่ยวข้องมีดังนี้

  • frontend มีส่วนหน้าของ App Engine ที่เราจะนำกลับมาใช้ใหม่จาก Lab 4
  • functions มี Cloud Functions ที่สร้างขึ้นสำหรับเวิร์กโฟลว์
  • services มีบริการ Cloud Run ที่แก้ไขสำหรับเวิร์กโฟลว์
  • workflows.yaml คือไฟล์คำจำกัดความของเวิร์กโฟลว์

6. สำรวจ YAML ของเวิร์กโฟลว์

workflows.yaml จะกำหนดเวิร์กโฟลว์ในชุดขั้นตอน มาดูรายละเอียดเพื่อทำความเข้าใจให้ดียิ่งขึ้นกัน

ที่จุดเริ่มต้นของเวิร์กโฟลว์จะมีพารามิเตอร์บางอย่างที่ส่งเข้ามา โดย Cloud Functions 2 รายการจะส่งผ่านข้อมูลเหล่านี้เพื่อทริกเกอร์เวิร์กโฟลว์ เราจะพูดถึงฟังก์ชันเหล่านี้ในภายหลัง แต่เวิร์กโฟลว์จะเริ่มต้นดังนี้

d44a5e18aa9d4660.png

ใน YAML คุณจะเห็นว่าพารามิเตอร์เหล่านี้ได้รับการกำหนดให้กับตัวแปรในinitขั้นตอน เช่น ชื่อไฟล์และชื่อที่เก็บข้อมูลที่ทริกเกอร์เหตุการณ์ รวมถึง URL ของบริการ Cloud Functions และ Cloud Run บางอย่างที่ Workflows จะเรียกใช้

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}

จากนั้น เวิร์กโฟลว์จะตรวจสอบประเภทเหตุการณ์ ระบบรองรับเหตุการณ์ 2 ประเภท ได้แก่ object.finalize (ส่งออกเมื่อบันทึกไฟล์ใน Bucket ของพื้นที่เก็บข้อมูลบนคลาวด์) และ object.delete (ส่งออกเมื่อลบไฟล์) หากเป็นอย่างอื่น ระบบจะยกเว้นกิจกรรมที่ไม่รองรับ

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

สังเกตว่าเวิร์กโฟลว์รองรับคำสั่ง switch และการจัดการข้อยกเว้น โดยมีคำสั่ง switch และเงื่อนไขต่างๆ รวมถึงคำสั่ง raise เพื่อแจ้งข้อผิดพลาดเมื่อระบบไม่รู้จักเหตุการณ์

ต่อไป เรามาดูimageAnalysisCallกัน ซึ่งเป็นการเรียกใช้จากเวิร์กโฟลว์เพื่อเรียกใช้ Vision API เพื่อวิเคราะห์รูปภาพ แปลงข้อมูลการตอบกลับของ Vision API เพื่อจัดเรียงป้ายกำกับของสิ่งที่ระบบจดจำได้ในรูปภาพ เลือกสีเด่น ตรวจสอบว่ารูปภาพปลอดภัยที่จะแสดงหรือไม่ แล้วบันทึกข้อมูลเมตาไปยัง Cloud Firestore

โปรดทราบว่าทุกอย่างจะดำเนินการในเวิร์กโฟลว์ ยกเว้นฟังก์ชัน Cloud ของ Vision Transform (ซึ่งเราจะติดตั้งใช้งานในภายหลัง)

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

เมื่อวิเคราะห์รูปภาพแล้ว 2 ขั้นตอนถัดไปคือการสร้างภาพขนาดย่อของรูปภาพและภาพคอลลาจของรูปภาพล่าสุด โดยการทำให้บริการ Cloud Run 2 รายการใช้งานได้และทำการเรียกไปยังบริการเหล่านั้นจากขั้นตอน 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 ทั้ง 2 อย่างนี้ดำเนินการด้วยการเรียก 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 Functions, บริการ Cloud Run และฐานข้อมูล Firestore

7. สร้างที่เก็บข้อมูล

คุณต้องมี 2 บัคเก็ตสำหรับรูปภาพ ได้แก่ 1 บัคเก็ตสำหรับบันทึกรูปภาพต้นฉบับความละเอียดสูง และ 1 บัคเก็ตสำหรับบันทึกภาพขนาดย่อของรูปภาพ

สร้างที่เก็บข้อมูลสาธารณะระดับภูมิภาค (ในกรณีนี้คือในยุโรป) ที่มีการเข้าถึงแบบเดียวกันเพื่อให้ผู้ใช้อัปโหลดรูปภาพได้โดยใช้เครื่องมือ 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}

คุณตรวจสอบอีกครั้งได้ว่ามีการสร้างที่เก็บข้อมูลและที่เก็บข้อมูลเป็นแบบสาธารณะโดยไปที่ส่วน Cloud Storage ของ Cloud Console

15063936edd72f06.png

8. การเปลี่ยนรูปแบบข้อมูล Vision (Cloud Function)

Workflows.yaml เริ่มต้นด้วยขั้นตอน init, eventTypeSwitch, eventTypeNotSupported ซึ่งจะช่วยให้มั่นใจได้ว่าระบบจะกำหนดเส้นทางเหตุการณ์ที่มาจากที่เก็บข้อมูลไปยังขั้นตอนที่ถูกต้อง

สำหรับเหตุการณ์ object.finalize ขั้นตอน imageAnalysisCall จะเรียกใช้ Vision API เพื่อดึงข้อมูลเมตาของรูปภาพที่สร้างขึ้น ขั้นตอนทั้งหมดนี้ดำเนินการภายในเวิร์กโฟลว์

daaed43a22d2b0d3.png

จากนั้นเราต้องเปลี่ยนรูปแบบข้อมูลที่ Vision API ส่งคืนมาก่อนจึงจะบันทึกลงใน Firestore ได้ โดยเฉพาะอย่างยิ่ง เราต้องดำเนินการต่อไปนี้

  • แสดงรายการป้ายกำกับที่แสดงผลสำหรับรูปภาพ
  • ดึงสีเด่นของรูปภาพ
  • พิจารณาว่ารูปภาพปลอดภัยหรือไม่

โดยจะดำเนินการในโค้ดใน Cloud Function และเวิร์กโฟลว์จะเรียกใช้ฟังก์ชันนี้

5e120e70c67779cd.png

สำรวจโค้ด

Cloud Function มีชื่อว่า vision-data-transform คุณสามารถดูโค้ดทั้งหมดได้ใน index.js ดังที่เห็นได้ว่า ฟังก์ชันนี้มีจุดประสงค์เพียงอย่างเดียวคือการแปลง JSON เป็น JSON เพื่อจัดเก็บข้อมูลเมตาของรูปภาพใน Firestore ได้อย่างสะดวก

ทำให้ใช้งานได้กับ Cloud Functions

ไปที่โฟลเดอร์

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 ของเวิร์กโฟลว์จะเรียกใช้ฟังก์ชันนี้เพื่อทำการเปลี่ยนรูปแบบข้อมูล Vision API ได้

9. เตรียมฐานข้อมูล

ขั้นตอนถัดไปในเวิร์กโฟลว์คือการตรวจสอบความปลอดภัยของรูปภาพจากข้อมูลรูปภาพ แล้วจัดเก็บข้อมูลเกี่ยวกับรูปภาพที่ Vision API ส่งคืนลงในฐานข้อมูล Cloud Firestore ซึ่งเป็นฐานข้อมูลเอกสาร NoSQL ที่รวดเร็ว มีการจัดการเต็มรูปแบบ แบบ Serverless และทำงานบนระบบคลาวด์

6624c616bc7cd97f.png

ทั้ง 2 อย่างนี้ทำได้ในเวิร์กโฟลว์ แต่คุณต้องสร้างฐานข้อมูล Firestore เพื่อให้การจัดเก็บข้อมูลเมตาทำงานได้

ก่อนอื่น ให้สร้างแอป App Engine ในภูมิภาคที่คุณต้องการฐานข้อมูล Firestore (ข้อกำหนดสำหรับ Firestore) โดยทำดังนี้

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

จากนั้นสร้างฐานข้อมูล Firestore ในภูมิภาคเดียวกันโดยทำดังนี้

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

ระบบจะสร้างเอกสารแบบเป็นโปรแกรมในคอลเล็กชันของเรา และจะมี 4 ฟิลด์ ได้แก่

  • name (สตริง): ชื่อไฟล์ของรูปภาพที่อัปโหลด ซึ่งเป็นคีย์ของเอกสารด้วย
  • ป้ายกำกับ (อาร์เรย์ของสตริง): ป้ายกำกับของรายการที่ Vision API รู้จัก
  • color (สตริง): รหัสสีเลขฐานสิบหกของสีหลัก (เช่น #ab12ef)
  • สร้าง (วันที่): การประทับเวลาเมื่อจัดเก็บข้อมูลเมตาของรูปภาพนี้
  • thumbnail (บูลีน): ฟิลด์ที่ไม่บังคับซึ่งจะแสดงและมีค่าเป็นจริงหากมีการสร้างภาพขนาดย่อสำหรับรูปภาพนี้

เนื่องจากเราจะค้นหาใน Firestore เพื่อหารูปภาพที่มีภาพขนาดย่อ และจัดเรียงตามวันที่สร้าง เราจึงต้องสร้างดัชนีการค้นหา คุณสร้างดัชนีได้ด้วยคำสั่งต่อไปนี้

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 ได้แล้ว

10. บริการภาพปก (Cloud Run)

ขั้นตอนถัดไปคือการสร้างภาพขนาดย่อของรูปภาพ โดยจะดำเนินการในโค้ดในบริการ Cloud Run และเวิร์กโฟลว์จะเรียกใช้บริการนี้ใน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}

หลังจากผ่านไป 1-2 นาที การบิลด์ควรจะสำเร็จและระบบจะนำคอนเทนเนอร์ไปใช้งานใน Google Container Registry

ทำให้ใช้งานได้กับ 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}

เมื่อติดตั้งใช้งานบริการแล้ว ขั้นตอน Workflows thumbnailCall จะเรียกใช้บริการนี้ได้

11. บริการภาพคอลลาจ (Cloud Run)

ขั้นตอนถัดไปคือการสร้างภาพคอลลาจจากรูปภาพล่าสุด โดยจะดำเนินการในโค้ดในบริการ Cloud Run และเวิร์กโฟลว์จะเรียกใช้บริการนี้ใน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}

หลังจากผ่านไป 1-2 นาที การบิลด์ควรจะสำเร็จและระบบจะนำคอนเทนเนอร์ไปใช้งานใน Google Container Registry

ทำให้ใช้งานได้กับ 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}

เมื่อติดตั้งใช้งานบริการแล้ว คุณจะตรวจสอบได้ว่าทั้ง 2 บริการทำงานอยู่ในส่วน Cloud Run ของ Cloud Console และขั้นตอน Workflows collageCall จะเรียกใช้บริการนี้ได้

3ae9873f4cbbf423.png

12. การติดตั้งใช้งานเวิร์กโฟลว์

เราได้ติดตั้งใช้งานการอ้างอิงภายนอกทั้งหมดของเวิร์กโฟลว์แล้ว Workflows จะทำขั้นตอนที่เหลือทั้งหมด (finalizeCompleted, pictureGarbageCollectionGCS, pictureGarbageCollectionFirestore, deleteCompleted) ให้เสร็จสมบูรณ์ได้เอง

ได้เวลาใช้งานเวิร์กโฟลว์แล้ว

ไปที่โฟลเดอร์ที่มีไฟล์ 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

คุณคลิกเวิร์กโฟลว์และแก้ไขได้หากต้องการ ในระหว่างการแก้ไข คุณจะเห็นภาพที่แสดงเวิร์กโฟลว์อย่างชัดเจน

55441b158f6027f3.png

นอกจากนี้ คุณยังเรียกใช้เวิร์กโฟลว์จาก Cloud Console ด้วยตนเองโดยใช้พารามิเตอร์ที่ถูกต้องได้ด้วย แต่เราจะดำเนินการโดยอัตโนมัติเพื่อตอบสนองต่อเหตุการณ์ใน Cloud Storage ในขั้นตอนถัดไป

13. ทริกเกอร์เวิร์กโฟลว์ (Cloud Functions)

เวิร์กโฟลว์ได้รับการติดตั้งใช้งานและพร้อมแล้ว ตอนนี้เราต้องทริกเกอร์เวิร์กโฟลว์เมื่อมีการสร้างหรือลบไฟล์ใน Bucket ของ Cloud Storage ซึ่งก็คือเหตุการณ์ storage.object.finalize และ storage.object.delete ตามลำดับ

เวิร์กโฟลว์มี API และไลบรารีของไคลเอ็นต์สำหรับการสร้าง จัดการ และเรียกใช้เวิร์กโฟลว์ที่คุณใช้ได้ ในกรณีนี้ คุณจะใช้ Workflows Execution API และโดยเฉพาะอย่างยิ่ง ไลบรารีของไคลเอ็นต์ Node.js เพื่อทริกเกอร์เวิร์กโฟลว์

คุณจะทริกเกอร์เวิร์กโฟลว์จาก Cloud Function ที่รับฟังเหตุการณ์ Cloud Storage เนื่องจาก Cloud Functions รับฟังได้เพียงเหตุการณ์ประเภทเดียว คุณจึงต้องติดตั้งใช้งาน Cloud Functions 2 รายการเพื่อรับฟังทั้งเหตุการณ์การสร้างและการลบ

c4d79646de729e4.png

สำรวจโค้ด

Cloud Function มีชื่อว่า trigger-workflow คุณสามารถดูโค้ดทั้งหมดได้ใน index.js

ทำให้ใช้งานได้กับ Cloud Functions

ไปที่โฟลเดอร์

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}

ทำให้ฟังก์ชันที่ 2 ที่ตอบสนองต่อเหตุการณ์การลบใช้งานได้

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}

เมื่อการติดตั้งใช้งานเสร็จสมบูรณ์ คุณจะเห็นทั้ง 2 ฟังก์ชันใน Cloud Console ดังนี้

7d60c8b7851f39f5.png

14. ส่วนหน้า (App Engine)

ในขั้นตอนนี้ คุณจะสร้างส่วนหน้าของเว็บใน Google App Engine จาก Pic-a-daily: Lab 4 - สร้างส่วนหน้าของเว็บ ซึ่งจะช่วยให้ผู้ใช้อัปโหลดรูปภาพจากเว็บแอปพลิเคชัน รวมถึงเรียกดูรูปภาพที่อัปโหลดและภาพขนาดย่อได้

223fb2281614d053.png

ดูข้อมูลเพิ่มเติมเกี่ยวกับ App Engine และอ่านคำอธิบายโค้ดได้ใน Pic-a-daily: Lab 4—Create a web frontend

สำรวจโค้ด

แอป App Engine มีชื่อว่า frontend คุณสามารถดูโค้ดทั้งหมดได้ใน index.js

ทำให้ใช้งานได้กับ App Engine

ไปที่โฟลเดอร์

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

หลังจากผ่านไป 1-2 นาที ระบบจะแจ้งว่าแอปพลิเคชันกำลังให้บริการการรับส่งข้อมูล

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 เช่น การควบคุมเวอร์ชันและการแยกการรับส่งข้อมูลได้ด้วย

f4bd5f4de028bd83.png

15. ทดสอบเวิร์กโฟลว์

หากต้องการทดสอบ ให้ไปที่ URL ของ App Engine เริ่มต้นสำหรับแอป (https://<YOUR_PROJECT_ID>.appspot.com/) แล้วคุณจะเห็น UI ส่วนหน้าทำงาน

1649ac060441099.png

อัปโหลดรูปภาพ ซึ่งควรจะทริกเกอร์เวิร์กโฟลว์และคุณจะเห็นการดำเนินการเวิร์กโฟลว์ในสถานะ Active ใน Cloud Console

b5a2a3d7a2bc094.png

เมื่อเวิร์กโฟลว์เสร็จสมบูรณ์แล้ว คุณสามารถคลิกรหัสการดำเนินการและดูเอาต์พุตจากบริการต่างๆ ได้ดังนี้

8959df5098c21548.png

อัปโหลดรูปภาพอีก 3 รูป นอกจากนี้ คุณควรเห็นภาพขนาดย่อและภาพคอลลาจของรูปภาพใน Bucket ของ Cloud Storage และส่วนหน้าของ App Engine ที่อัปเดตแล้วด้วย

d90c786ff664a5dc.png

16. ล้างข้อมูล (ไม่บังคับ)

หากไม่ต้องการเก็บแอปไว้ คุณสามารถล้างข้อมูลทรัพยากรเพื่อประหยัดค่าใช้จ่ายและเป็นพลเมืองที่ดีของระบบคลาวด์โดยรวมได้โดยการลบทั้งโปรเจ็กต์ ดังนี้

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

17. ยินดีด้วย

คุณสร้างแอปเวอร์ชันที่จัดระเบียบโดยใช้เวิร์กโฟลว์เพื่อจัดระเบียบและเรียกใช้บริการ

สิ่งที่เราได้พูดถึง

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • เวิร์กโฟลว์