检查点
Build simple a REST API
/ 20
Create a Revision for Cloud Run
/ 20
Create two cloud storage buckets
/ 10
Create a Pub/Sub topic for receiving notification from storage bucket
/ 10
Create a Pub/Sub subscription
/ 10
Create another build for REST API
/ 15
Create a new Revision
/ 15
使用 Cloud Run 建構可建立 PDF 檔案的無伺服器應用程式
GSP644
總覽
Pet Theory 是莉莉在 12 年前創立的連鎖獸醫診所。 目前 Pet Theory 是用 DOCX 格式為顧客開發票,但是很多顧客都抱怨打不開檔案。 為提高顧客滿意度,莉莉已經請 IT 部門的阿克研究替代方案,希望能改善現況。
Pet Theory 的營運團隊只有一個人,因此對他們而言,不需要大量持續維護的解決方案更符合成本效益,是理想的投資選擇。阿克分析了各種處理方案,最後決定使用 Cloud Run。
Cloud Run 採用無伺服器技術,可以省去所有基礎架構管理工作,讓您專心建構應用程式,不必擔心開銷問題。這項 Google 無伺服器產品能將資源調度率降至零,這意味著不使用就不會產生費用。此外,Cloud Run 也支援使用以容器為基礎的自訂二進位檔套件,因此能建構一致且隔離的構件。
在本實驗室中,您將於 Cloud Run 建構 PDF 轉換器網頁應用程式,並能利用這個應用程式,自動將 Cloud Storage 中的檔案轉換為 PDF,儲存至個別資料夾。
架構
下方圖表列出了您將使用的服務,以及這些服務之間的關係:
目標
本實驗室的學習內容包括:
- 將 Node JS 應用程式轉換成容器。
- 使用 Google Cloud Build 建構容器。
- 建構可將雲端檔案轉換成 PDF 檔案的 Cloud Run 服務。
- 將事件處理功能與 Cloud Storage 搭配使用。
先備知識
本實驗室的難度為中級,參加基本條件是熟悉 Cloud 控制台和殼層環境。具備 Firebase 的使用經驗會有所幫助,但沒有也無妨。參加本實驗室前,建議您完成下列 Google Cloud Skills Boost 實驗室:
準備完成後,即可向下捲動頁面,按照步驟設定實驗室環境。
設定和需求
點選「Start Lab」按鈕前的須知事項
請詳閱以下操作說明。研究室活動會計時,而且中途無法暫停。點選「Start Lab」 後就會開始計時,讓您瞭解有多少時間可以使用 Google Cloud 資源。
您將在真正的雲端環境中完成實作研究室活動,而不是在模擬或示範環境。為達此目的,我們會提供新的暫時憑證,讓您用來在研究室活動期間登入及存取 Google Cloud。
如要完成這個研究室活動,請先確認:
- 您可以使用標準的網際網路瀏覽器 (Chrome 瀏覽器為佳)。
- 是時候完成研究室活動了!別忘了,活動一開始將無法暫停。
如何開始研究室及登入 Google Cloud 控制台
-
按一下「Start Lab」(開始研究室) 按鈕。如果研究室會產生費用,畫面中會出現選擇付款方式的彈出式視窗。左側的「Lab Details」窗格會顯示下列項目:
- 「Open Google Cloud console」按鈕
- 剩餘時間
- 必須在這個研究室中使用的暫時憑證
- 完成這個實驗室所需的其他資訊 (如有)
-
點選「Open Google Cloud console」;如果使用 Chrome 瀏覽器,也能按一下滑鼠右鍵,然後選取「在無痕式視窗中開啟連結」。
接著,實驗室會啟動相關資源並開啟另一個分頁,當中顯示「登入」頁面。
提示:您可以在不同的視窗中並排開啟分頁。
注意:如果頁面中顯示「選擇帳戶」對話方塊,請點選「使用其他帳戶」。 -
如有必要,請將下方的 Username 貼到「登入」對話方塊。
{{{user_0.username | "Username"}}} 您也可以在「Lab Details」窗格找到 Username。
-
點選「下一步」。
-
複製下方的 Password,並貼到「歡迎使用」對話方塊。
{{{user_0.password | "Password"}}} 您也可以在「Lab Details」窗格找到 Password。
-
點選「下一步」。
重要事項:請務必使用實驗室提供的憑證,而非自己的 Google Cloud 帳戶憑證。 注意:如果使用自己的 Google Cloud 帳戶來進行這個實驗室,可能會產生額外費用。 -
按過後續的所有頁面:
- 接受條款及細則。
- 由於這是臨時帳戶,請勿新增救援選項或雙重驗證機制。
- 請勿申請免費試用。
Google Cloud 控制台稍後會在這個分頁開啟。
啟動 Cloud Shell
Cloud Shell 是搭載多項開發工具的虛擬機器,提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作。Cloud Shell 提供指令列存取權,方便您使用 Google Cloud 資源。
- 點按 Google Cloud 控制台上方的「啟用 Cloud Shell」圖示 。
連線完成即代表已通過驗證,且專案已設為您的 PROJECT_ID。輸出內容中有一行宣告本工作階段 PROJECT_ID 的文字:
gcloud
是 Google Cloud 的指令列工具,已預先安裝於 Cloud Shell,並支援 Tab 鍵自動完成功能。
- (選用) 您可以執行下列指令來列出使用中的帳戶:
-
點按「授權」。
-
輸出畫面應如下所示:
輸出內容:
- (選用) 您可以使用下列指令來列出專案 ID:
輸出內容:
輸出內容範例:
gcloud
的完整說明,請前往 Google Cloud 並參閱「gcloud CLI overview guide」(gcloud CLI 總覽指南)。
工作 1:瞭解工作內容
Pet Theory 想將發票轉換成顧客容易開啟的 PDF 格式,同時也希望這項轉換作業能自動化,盡量減輕行政主管麗莎的工作負擔。
小茹是 Pet Theory 的電腦顧問,她從 IT 部門的阿克那裡收到訊息...
IT 管理員阿克 |
小茹你好: 我研究發現,LibreOffice 可以將很多種格式轉換成 PDF 檔, 我們是否能在雲端執行 LibreOffice,省去維護伺服器的麻煩? 阿克 |
軟體顧問小茹 |
阿克你好: 我正好有合適的解決方案。 我剛在 YouTube 看了一部 2019 年 Next 大會的精彩影片,內容是關於 Cloud Run。看起來,我們可以利用 Cloud Run 在無伺服器的環境中執行 LibreOffice,完全不需要維護伺服器! 我會傳送一些資源來協助你設定。 小茹 |
請協助阿克設定與部署 Cloud Run。
工作 2:啟用 Cloud Run API
-
開啟「導覽選單」 (),依序點選「API 和服務」>「程式庫」。在搜尋列中輸入「Cloud Run」,從結果選單中選取「Cloud Run Admin API」。
-
按一下「啟用」,點選瀏覽器中的返回按鈕「兩次」。這時控制台應顯示類似下方的畫面:
工作 3:部署簡易的 Cloud Run 服務
小茹希望阿克將她開發的 Cloud Run 原型部署至 Google Cloud。現在您需要協助阿克為 Pet Theory 建立轉檔成 PDF 的 Cloud Run 服務。
-
開啟新的 Cloud Shell 工作階段,執行以下指令來複製 Pet Theory 存放區:
git clone https://github.com/rosera/pet-theory.git -
接著,將目前的工作目錄改成 lab03:
cd pet-theory/lab03 -
使用 Cloud Shell 程式碼編輯器或您慣用的文字編輯器,編輯
package.json
。在「scripts」部分中加入"start": "node index.js",
,如下所示:... "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, ... -
接著在 Cloud Shell 中執行以下指令,安裝轉換指令碼將使用的套件:
npm install express npm install body-parser npm install child_process npm install @google-cloud/storage -
開啟
lab03/index.js
檔案並檢查程式碼。這個應用程式將部署為 Cloud Run 服務,並接受 HTTP POST。當 POST 要求是有關上傳檔案的 Pub/Sub 通知,服務就會將檔案詳情寫入記錄;如果不是,則會直接傳回「OK」字串。
-
檢查名為
lab03/Dockerfile
的檔案。上述檔案稱為資訊清單,Docker 指令會按照當中提供的方案建構映像檔。每行以指令開頭,告訴 Docker 如何處理以下資訊:
- 第一份清單指出,基本映像檔應將節點做為範本來建立映像檔。
- 最後一行指示要執行的指令,本例中為「npm start」。
-
如要建構及部署 REST API,請使用 Google Cloud Build。執行以下指令,即可啟動建構程序:
gcloud builds submit \ --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter 該指令會使用您的程式碼建構容器,並將其放入專案的 Artifact Registry。
-
返回 Cloud 控制台,開啟導覽選單,然後依序選取「Artifact Registry」>「映像檔」。畫面上應會顯示您的託管容器:
測試工作已完成
點選「Check my progress」確認上述工作已完成。
-
返回程式碼編輯器分頁,在 Cloud Shell 中執行以下指令碼來部署應用程式:
gcloud run deploy pdf-converter \ --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \ --platform managed \ --region {{{ project_0.default_region | Region }}} \ --no-allow-unauthenticated \ --max-instances=1 -
部署作業完成後,您會看到類似下方的訊息:
Service [pdf-converter] revision [pdf-converter-00001] has been deployed and is serving 100 percent of traffic at https://pdf-converter-[hash].a.run.app -
建立
$SERVICE_URL
環境變數,這樣就能輕鬆存取應用程式:SERVICE_URL=$(gcloud beta run services describe pdf-converter --platform managed --region {{{ project_0.default_region | Lab Region }}} --format="value(status.url)") echo $SERVICE_URL
測試工作已完成
點選「Check my progress」確認上述工作已完成。
-
對新服務提出去識別化的 POST 要求:
curl -X POST $SERVICE_URL 注意:
這會導致系統顯示「Your client does not have permission to get the URL」錯誤訊息。這樣很好,因為您不會希望匿名使用者能呼叫服務。 -
接著嘗試以授權使用者的身分叫用服務:
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL 如果收到
"OK"
回覆,表示已成功部署 Cloud Run 服務,做得好!
工作 4:在上傳新檔案時觸發 Cloud Run 服務
成功部署 Cloud Run 服務後,小茹希望阿克建立一個暫存區,用來容納需要轉換的資料。每當有上傳的檔案需要處理,Cloud Storage bucket 就會使用事件觸發條件通知應用程式。
-
執行以下指令,在 Cloud Storage 中建立容納上傳文件的 bucket:
gsutil mb gs://$GOOGLE_CLOUD_PROJECT-upload -
以及容納處理後 PDF 的 bucket:
gsutil mb gs://$GOOGLE_CLOUD_PROJECT-processed -
接著返回 Cloud 控制台分頁,開啟「導覽選單」並選取「Cloud Storage」。請確認所需 bucket 已建立完成 (畫面上也會列出平台使用的其他 bucket)。
測試工作已完成
點選「Check my progress」確認上述工作已完成。
-
在 Cloud Shell 中執行以下指令,指示 Cloud Storage 在新檔案已上傳至 docs bucket 時傳送 Pub/Sub 通知:
gsutil notification create -t new-doc -f json -e OBJECT_FINALIZE gs://$GOOGLE_CLOUD_PROJECT-upload 這類通知會加上「new-doc」主題標籤。
測試工作已完成
點選「Check my progress」確認上述工作已完成。
-
接著建立新的服務帳戶,以供 Pub/Sub 觸發 Cloud Run 服務使用:
gcloud iam service-accounts create pubsub-cloud-run-invoker --display-name "PubSub Cloud Run Invoker" -
為新服務帳戶授予叫用 PDF 轉換器服務的權限:
gcloud beta run services add-iam-policy-binding pdf-converter \ --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --role=roles/run.invoker \ --platform managed \ --region {{{ project_0.default_region | Lab Region }}} -
執行以下指令,找出您的專案編號:
gcloud projects list --filter="PROJECT_ID={{{ project_0.project_id | PROJECT_ID }}}" 您將在下一個指令中使用這個專案編號值。
PROJECT_ID: {{{ project_0.project_id | PROJECT_ID }}} NAME: {{{ project_0.project_id | PROJECT_ID }}} PROJECT_NUMBER: 103480415252 -
建立
PROJECT_NUMBER
環境變數PROJECT_NUMBER=$(gcloud projects list --filter="PROJECT_ID={{{ project_0.project_id | PROJECT_ID }}}" --format=json | jq -r .[0].projectNumber) -
最後,請建立 Pub/Sub 訂閱項目,以便在任何「new-doc」主題的訊息發布時執行 PDF 轉換器。
gcloud beta pubsub subscriptions create pdf-conv-sub \ --topic new-doc \ --push-endpoint=$SERVICE_URL \ --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
測試工作已完成
點選「Check my progress」確認上述工作已完成。
工作 5:看看新檔案上傳至 Cloud Storage 是否會觸發 Cloud Run 服務
為確認應用程式能正常運作,小茹請阿克將一些測試資料上傳至指定的 Storage bucket,然後查看 Cloud Logging。
-
將一些測試檔案複製到 upload bucket:
gsutil -m cp gs://spls/gsp644/* gs://$GOOGLE_CLOUD_PROJECT-upload -
上傳完畢後,請返回 Cloud 控制台分頁,開啟導覽選單,然後在「作業」部分底下選取「記錄」。
-
在「資源」下拉式選單中,選擇篩選條件為「Cloud Run 修訂版本」並點選「套用」,接著點選「執行查詢」。
-
在「查詢結果」中找出並點選
file:
開頭的記錄項目。這是新檔案上傳時,Pub/Sub 傳送至 Cloud Run 服務的檔案資料傾印。 -
您可以在這個物件中找到已上傳檔案的名稱嗎?
注意:
如果找不到「file」開頭的記錄項目,請點選頁面底部附近的「load newer logs」按鈕。 -
返回程式碼編輯器分頁,在 Cloud Shell 中執行以下指令,徹底刪除
upload
目錄中的檔案:gsutil -m rm gs://$GOOGLE_CLOUD_PROJECT-upload/*
工作 6:容器
阿克需要將待處理的發票轉換成 PDF 檔,確保所有顧客都能開啟檔案。他透過郵件向小茹尋求協助...
IT 管理員阿克 |
小茹你好: 根據你調查到的資訊,我想可以將這個流程自動化,開始使用 PDF 做為發票格式。 我昨天花點時間編寫了解決方案,也根據我們需要的功能,建構了相應的 Node.js 指令碼。你可以看一下嗎? 阿克 |
阿克編寫了能從檔案產生 PDF 的程式碼片段,然後寄給小茹:
小茹回覆阿克...
軟體顧問小茹 |
阿克你好: Cloud Run 會使用容器,所以我們要以這個格式提供應用程式。下一步,我們需要建立應用程式的 Dockerfile 資訊清單。 您的程式碼使用了 LibreOffice,可以將安裝這個軟體的指令寄給我嗎?我需要將這段程式碼加入容器。 小茹 |
IT 管理員阿克 |
小茹你好: 沒問題,以下是我平常在辦公室伺服器上安裝 LibreOffice 所用的指令:
如果需要更多資訊,儘管告訴我。 阿克 |
建構容器時,需要整合的元件如下:
更新資訊清單
辨識出所有檔案後,就可以開始建立資訊清單了。請幫助小茹設定與部署容器。
容器原本不含 LibreOffice 套件,所以現在需要額外加入。
阿克已經將建構這個應用程式的指令交給小茹,小茹會將這些做為 RUN
指令加入 Dockerfile。
-
開啟
Dockerfile
資訊清單,加入RUN apt-get update -y && apt-get install -y libreoffice && apt-get clean
指令,如下所示:LFROM {{{ project_0.startup_script.node_version | NODE_VERSION }}} RUN apt-get update -y \ && apt-get install -y libreoffice \ && apt-get clean WORKDIR /usr/src/app COPY package.json package*.json ./ RUN npm install --only=production COPY . . CMD [ "npm", "start" ]
部署新版 PDF 轉換服務
-
開啟
index.js
檔案,在最上方加入以下套件需求:const {promisify} = require('util'); const {Storage} = require('@google-cloud/storage'); const exec = promisify(require('child_process').exec); const storage = new Storage(); -
將
app.post('/', async (req, res)
替換為以下程式碼:app.post('/', async (req, res) => { try { const file = decodeBase64Json(req.body.message.data); await downloadFile(file.bucket, file.name); const pdfFileName = await convertFile(file.name); await uploadFile(process.env.PDF_BUCKET, pdfFileName); await deleteFile(file.bucket, file.name); } catch (ex) { console.log(`Error: ${ex}`); } res.set('Content-Type', 'text/plain'); res.send('\n\nOK\n\n'); }) -
在檔案最下方加入處理 LibreOffice 文件的程式碼:
async function downloadFile(bucketName, fileName) { const options = {destination: `/tmp/${fileName}`}; await storage.bucket(bucketName).file(fileName).download(options); } async function convertFile(fileName) { const cmd = 'libreoffice --headless --convert-to pdf --outdir /tmp ' + `"/tmp/${fileName}"`; console.log(cmd); const { stdout, stderr } = await exec(cmd); if (stderr) { throw stderr; } console.log(stdout); pdfFileName = fileName.replace(/\.\w+$/, '.pdf'); return pdfFileName; } async function deleteFile(bucketName, fileName) { await storage.bucket(bucketName).file(fileName).delete(); } async function uploadFile(bucketName, fileName) { await storage.bucket(bucketName).upload(`/tmp/${fileName}`); } -
確認
index.js
檔案內容類似下方程式碼:注意:
為避免格式錯誤,建議您將index.js
檔案中的程式碼都換成範例程式碼。const {promisify} = require('util'); const {Storage} = require('@google-cloud/storage'); const exec = promisify(require('child_process').exec); const storage = new Storage(); const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); const port = process.env.PORT || 8080; app.listen(port, () => { console.log('Listening on port', port); }); app.post('/', async (req, res) => { try { const file = decodeBase64Json(req.body.message.data); await downloadFile(file.bucket, file.name); const pdfFileName = await convertFile(file.name); await uploadFile(process.env.PDF_BUCKET, pdfFileName); await deleteFile(file.bucket, file.name); } catch (ex) { console.log(`Error: ${ex}`); } res.set('Content-Type', 'text/plain'); res.send('\n\nOK\n\n'); }) function decodeBase64Json(data) { return JSON.parse(Buffer.from(data, 'base64').toString()); } async function downloadFile(bucketName, fileName) { const options = {destination: `/tmp/${fileName}`}; await storage.bucket(bucketName).file(fileName).download(options); } async function convertFile(fileName) { const cmd = 'libreoffice --headless --convert-to pdf --outdir /tmp ' + `"/tmp/${fileName}"`; console.log(cmd); const { stdout, stderr } = await exec(cmd); if (stderr) { throw stderr; } console.log(stdout); pdfFileName = fileName.replace(/\.\w+$/, '.pdf'); return pdfFileName; } async function deleteFile(bucketName, fileName) { await storage.bucket(bucketName).file(fileName).delete(); } async function uploadFile(bucketName, fileName) { await storage.bucket(bucketName).upload(`/tmp/${fileName}`); }
- 主要邏輯在以下函式中:
每當有檔案上傳,就會觸發這項服務。執行下列工作 (上方每行程式碼各為一項工作):
- 從 Pub/Sub 通知擷取檔案詳情。
- 將檔案從 Cloud Storage 下載至本機硬碟。這個本機硬碟並不是實體磁碟,而是模擬磁碟行為的虛擬記憶體。
- 將下載的檔案轉換成 PDF。
- 將 PDF 檔案上傳至 Cloud Storage。
process.env.PDF_BUCKET
環境變數包含 PDF 將寫入的 Cloud Storage bucket 的名稱。您需要在部署下述服務時指定這個變數的值。 - 從 Cloud Storage 刪除原始檔案。
index.js
的其餘部分實作了此頂層程式碼呼叫的函式。
接著就該部署服務,設定 PDF_BUCKET
環境變數了。此外,將 2 GB RAM 分配給 LibreOffice 也是不錯的點子 (請見包含 --memory
選項的那一行)。
-
執行以下指令來建構容器:
gcloud builds submit \ --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter
如果收到提示啟用 Cloud Build API 的彈出式訊息,請輸入
Y
測試工作已完成
點選「Check my progress」確認上述工作已完成。
-
接著部署最新版本的應用程式:
gcloud run deploy pdf-converter \ --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \ --platform managed \ --region {{{ project_0.default_region | Lab Region }}} \ --memory=2Gi \ --no-allow-unauthenticated \ --max-instances=1 \ --set-env-vars PDF_BUCKET=$GOOGLE_CLOUD_PROJECT-processed
由於 LibreOffice 是容器的一部分,所以這次建構時間比上一次更長,您可以趁機起身活動一下。
點選「Check my progress」,確認目標已達成。
工作 7:測試 PDF 轉換服務
-
部署指令完成後,請執行以下指令,確認服務已正確部署:
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL -
如果收到
"OK"
回覆,表示已成功部署新版 Cloud Run 服務,LibreOffice 可以將多種檔案轉換成 PDF,比如 DOCX、XLSX、JPG、PNG、GIF 等。 -
執行以下指令,上傳範例檔案:
gsutil -m cp gs://spls/gsp644/* gs://$GOOGLE_CLOUD_PROJECT-upload -
返回 Cloud 控制台,開啟「導覽選單」並選取「Cloud Storage」。開啟
-upload
bucket,點選「重新整理」按鈕數次,查看轉換成 PDF 的檔案是如何逐一刪除。 -
接著在左選單中按一下「Bucket」,點選名稱結尾是「-processed」的 bucket。這個 bucket 應該包含所有檔案的 PDF 版本,您可以隨意點開 PDF 檔案檢查,確認沒問題:
注意:
如果-processed
bucket 未顯示部分轉換的 PDF 檔案,請重新執行指令。
恭喜!
Pet Theory 已有將封存舊檔轉換成 PDF 的系統。 只要將舊檔上傳至「upload」bucket,PDF 轉換器服務就會將這些檔案轉換成 PDF,並寫入「processed」bucket。
請修習「Serverless Cloud Run Development」課程,瞭解更多無伺服器開發知識。您將進入虛構的業務情境,協助其中角色完成無伺服器遷移計畫。
Google Cloud 教育訓練與認證
協助您瞭解如何充分運用 Google Cloud 的技術。我們的課程會介紹專業技能和最佳做法,讓您可以快速掌握要領並持續進修。我們提供從基本到進階等級的訓練課程,並有隨選、線上和虛擬課程等選項,方便您抽空參加。認證可協助您驗證及證明自己在 Google Cloud 技術方面的技能和專業知識。
使用手冊上次更新日期:2023 年 5 月 28 日
實驗室上次測試日期:2023 年 5 月 28 日
Copyright 2024 Google LLC 保留所有權利。Google 和 Google 標誌是 Google LLC 的商標,其他公司和產品名稱則有可能是其關聯公司的商標。