iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
IT Operation

從前後端踏上 AWS 雲端架構勇者之路系列 第 29 篇

串起整張架構:一次網站操作,AWS 在忙什麼?

  • 分享至 

  • xImage
  •  

前面我們講了很多 AWS 服務,從主機、資料庫,到圖片儲存、寄信,也都各自練習過了

那真的做一個網站時,這些服務要怎麼一起用呢?今天就把前面學過的內容串起來,用一個預約健身課的情境,看看每個步驟會用到哪些服務

假設小明要預約週五晚上的健身課。他先登入網站,換上個人照片,接著選好課程、按下預約,最後收到一封通知信。我們就跟著他的操作,一步一步往下看

小明登入網站,上傳照片並儲存,再預約週五十九點的健身課,最後收到通知信

這裡假設登入、照片上傳、預約功能都已經寫好,也部署好了。前面的 /health、/ready 只有檢查服務狀態,還沒有這些網站功能哦

先打開網站,再來登入

小明輸入網址後,瀏覽器先用 DNS 查到主機的 IP,再透過 HTTPS 連到 EC2。到了主機,先接收請求的是 Nginx,接著才轉給裡面的 Node.js Container

這次前端檔案跟 API 都放在同一個 Container。Node.js 提供 HTML、CSS、JavaScript,瀏覽器拿到這些檔案,才有登入畫面可以顯示

那畫面出來了,按下登入又會發生什麼事?

前端會把帳號、密碼送到登入 API,這個請求一樣先經過 Nginx,再交給 Node.js

我們的會員資料存在 RDS 的 PostgreSQL 資料庫。Node.js 要去查對應的帳號資料、核對登入資訊,才知道能不能讓小明登入

查完後,Node.js 把結果交給 Nginx,再由 Nginx 回給瀏覽器

登入成功,前端就切到會員頁面;帳密不對,就顯示登入失敗,讓小明重新輸入~

換照片啟用 S3 服務

小明登入後,從電腦選好照片。前端可以先讀本機檔案顯示預覽,接著再把圖片上傳

這裡先分清楚兩件事:圖片檔案放 S3,會員用了哪張圖片連結就記在 RDS。在小明那筆會員資料裡,除了姓名、信箱,也要記下照片在 S3 的完整名稱

所以接下來要先把圖片傳到 S3,再把照片名稱存進會員資料。下次回到這個頁面,程式才知道要顯示哪一張

不過我們的 Bucket 是私有的,瀏覽器要怎麼傳?

前端先跟 API 要一個上傳網址,也告訴它照片的檔案類型。Node.js 確認小明已登入、檔案類型是網站允許的,再替這張照片產生名稱,例如 members/a1b2c3.jpg

因為這台 EC2 綁定的 Role 有對應的 S3 權限,Node.js 才能替小明產生預簽名網址。網址指定要傳到哪個 Bucket、用哪個照片名稱,以及多久以內可以使用

API 把網址和照片名稱一起回給前端,前端就知道這次要把檔案傳去哪裡

注意這段的圖片檔案,是瀏覽器直接傳給 S3。Node.js 確認是誰要上傳、產生網址,不需要先收到整張照片再轉傳

下面是之前的 Bucket 畫面,Block all public access 仍然是 On。使用預簽名網址,不需要把整個 Bucket 改成公開

既有 S3 實拍:Block all public access 為 On,照片仍可透過有權限的預簽名網址上傳

照片上傳了,網站怎麼知道是誰的?

S3 收到 members/a1b2c3.jpg,但它不會幫我們更新小明的會員資料,所以接著還要按「儲存個人資料」

前端把 members/a1b2c3.jpg 送回 API。這個在 Bucket 裡的完整名稱,就叫 Object Key

程式先核對收到的 Key,是不是剛才允許小明上傳的那張照片,再存到他的會員資料。這樣去 RDS 查小明的資料,就找得到 S3 裡對應的圖片

那重新整理頁面時,照片要怎麼再出現?

API 先去 RDS 找小明的照片 Key,再用這個 Key 產生一個讀取網址,瀏覽器拿到後,向 S3 讀取圖片

上傳用的是 PUT,讀取用的是 GET,要分別產生對應的網址

這裡資料庫存 Key 就好。如果把整串讀取網址存進去,過期後拿它讀圖就會失敗,但圖片其實還在 S3。保存 Key,程式下次才能找到同一張照片,再產生新的讀取網址

也提醒下,拿到預簽名網址的人,在有效期間內也可能使用它,所以不要公開分享,也附上(S3 預簽名網址說明)

接著來預約週五的課程

照片存好了,小明選擇週五晚上七點的課程,按下「確認預約」。前端把這次選擇送到 API,請求也是經過 Nginx → Node.js

假設小明的頁面開著很久,這堂課已經停止接受預約,但他的畫面還留著預約按鈕。按下去就能訂到嗎?

所以收到請求後,Node.js 還要確認誰在預約、課程是否存在、現在能不能預約。已經不能預約,就回覆原因,讓小明重新選擇

確認可以預約後,Node.js 才把這筆資料寫進 RDS。簡化的描述會像這樣:

預約編號 會員 課程時間 狀態
123 小明 週五 19:00 已成立

等資料庫存好,API 再回覆預約已成立,前端才顯示成功。後面的畫面與通知信,也都能用編號 123 找到這一筆

小明只是在網站按按鈕,前端幫他發出 API 請求,連資料庫的則是 EC2 裡的 Node.js。下面是之前的 RDS 設定 Publicly accessible 是 No,資料庫繼續留在 Private Subnet,這裡就沿用前面準備好的私有連線

RDS 實拍(已移除游標):Publicly accessible 為 No,由 EC2 內的 API 連線處理資料

小明重新整理「我的預約」時,前端會再呼叫 API,Node.js 從 RDS 查回預約 123。所以關掉頁面再打開,這筆紀錄也就還在勒~

預約存好了,接下來寄通知信

存好預約 123 後,Node.js 整理收件信箱、課程名稱、時間,再呼叫 SES 寄信。像是主旨寫「預約成功,編號 123」,內文放週五晚上七點的課程資訊

信件內容由我們的程式準備,交給 SES 用已驗證的寄件身分寄出~

那如果預約已經存好了,寄信卻失敗,要怎麼辦?

先看這張圖,RDS 已經有預約 ID,後面呼叫 SES 時才出問題:

預約先保存到 RDS,再呼叫 SES;寄信失敗時保留預約,追蹤同一筆預約的通知狀態

這時預約還是成立。我會讓程式分開回報預約和通知結果,前端可以顯示「預約已成立,通知信暫時無法寄出」,小明到「我的預約」也找得到 123

SES 回傳 MessageId,代表它接受了寄送請求,還不表示小明已經收到信。接著去他的信箱找通知,主旨應該有預約編號 123,內文是週五晚上七點的課程,這樣就能跟網站上的那筆預約對起來,也附上(SES SendEmail)~

最後再回來看整張架構

剛才我們從登入、換照片,一路走到預約和通知信。現在把這些動作放回圖上,就比較知道每條線在做什麼了:

整體架構:瀏覽器經 Nginx 呼叫 Node.js,API 使用私有 RDS、私有 S3 與 SES;ECR 提供部署用映像檔

先來看中間,瀏覽器的 API 請求進到 EC2,經過 Nginx,再交給 Node.js。登入要查會員、預約要存紀錄,所以 Node.js 會連右邊的 RDS

換照片時,API 產生預簽名網址,照片檔案則從瀏覽器直接傳到左下方的 S3。圖中藍色虛線是網址的往返,向 API 要網址一樣會經過 Nginx

預約完成後,Node.js 再呼叫右上方的 SES,把通知寄到小明的信箱。資料庫存好、信件寄出

希望你會喜歡本篇用情境來進行綜觀講解,我們下篇見勒 :D


上一篇
CloudWatch Alarm 與 SNS:CPU 持續偏高,怎麼寄信通知我?
下一篇
網站上線後,怎麼檢查、退版與清理?
系列文
從前後端踏上 AWS 雲端架構勇者之路 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言