整理傳統型 Web 應用程式的背後運作

初次見面!
我是一位 35 歲、從零開始想成為工程師並每日努力的人。

剛開始學 Web 的時候,你有沒有遇過這種情況?

「畫面會動,但說不清楚背後到底發生了什麼……」

我也曾經是那樣的狀態。

本文要簡單整理、說明一下
傳統型 Web 應用程式的運作機制

這次會用「牛丼店」當作比喻,讓你用想像就能理解!

推薦閱讀對象

  • 一聽到「Web 應用的背後」,就覺得很難而停手的人
  • 一聽說「HTTP 是無狀態(stateless)」,覺得好像懂了但無法說清楚的人
  • 不太清楚「框架幫你做了哪些事」的人

參考書籍:小森裕介《成為專業人士的 Web 技術入門》


重點結論!

用一句話來說明傳統型 Web 應用程式,就是:

伺服器這個名為「單人店長」的人,每接到一個訂單就要照顧一個會失憶的打工仔,邊跟單邊從頭把全套料理重新做一遍再提供給顧客的狀態

……現場相當辛苦(笑)

一旦抓到這個想像,傳統型 Web 應用的運作就會變得相當清楚。

接下來逐步拆解說明。

Web 應用開發的痛點

製作 Web 應用困難的根本原因,在於它底層有「兩個棘手的特性」。

1. HTTP 是「每次都是第一次的打工(無狀態)」

連接瀏覽器與伺服器的規則叫做 HTTP,它有個性質叫做 無狀態(stateless)

打個比方,就是「每次請求都會被重置記憶的打工仔」。

我:「我要一碗牛丼!」

打工:「好的,牛丼一碗!」(提供)

我:「啊,想再加一顆生蛋!」

打工:「……抱歉,您是第一次來嗎?」

剛才的互動,全部都被重置了。

很可惜,如果不每次都自我介紹「我是剛剛點牛丼的那位」,伺服器不會把你當同一個人看待。

這就是 無狀態 的真面目。

2. 同時會有 100 個人來下單(多使用者同時使用)

Web 應用通常會同時有數百甚至更多的使用者在使用。
想像一個會失憶的打工仔前面同時站著 100 個人,高聲喊著「牛丼!」、「咖哩!」。
伺服器必須絕對不弄錯地處理這些同時發生的請求。

傳統型 Web 應用的「蠻力」解法

面對「失憶」與「大排長龍」這兩個嚴苛情況,傳統型 Web 應用採取的是「伺服器(單人店長)每次都從零重新做出一個完成品並送出」的超級蠻力做法。

具體來說,大致如下:

調理與盛盤通通由店長(伺服器)負責產生 HTML

顧客(瀏覽器)只要在位子上等待。從後端的計算到「丼飯的擺盤(HTML 組合)」全部由伺服器處理。瀏覽器只是把「端上來的完成牛丼(已渲染好的 HTML)」吃掉(顯示)而已,是個被動的存在。

只要加一顆生蛋,就把牛丼從零開始重做(畫面跳轉的機制)

按下連結移動到另一個畫面(畫面遷移),就像對店家說「還是想加生蛋!」。
一般來說只要把生蛋單獨端上一小碟就好,但傳統型應用不是這樣做。
它會把你正在吃的牛丼收回,廚房裡從頭做一碗「一開始就有生蛋的新牛丼」,再端出來。
按下連結畫面會短暫變白一閃,正是因為發生了這種「整碗(整個畫面)被強制交換」的動作。
※ 瀏覽器會把頁面重置一次,重新載入新的 HTML。

補救失憶的「Cookie 與 Session」

最大問題是:「要怎麼讓那個會失憶的打工仔記得你?」

答案就是「會話(Session)」和「Cookie」!

  • 會話(Session,伺服器的私下備忘)
    伺服器(店長)在背後為我們專門做一張「訂單備忘錄」。
    裡面偷偷寫下「這個人已經點了牛丼」之類的資訊。

  • 會話 ID(兌換券編號)
    為了對照那張備忘錄,伺服器會發一張「兌換券(編號)」給你。

  • Cookie(放在顧客錢包中的東西)
    店長把兌換券交給瀏覽器(顧客),請它「放在錢包(Cookie)裡保存」。

之後顧客每次下單都會遵守「從錢包(Cookie)拿出兌換券(會話 ID)給店長看」的規則。
這樣打工仔就能說:「喔,兌換券 999 的牛丼客人對吧!」然後去看那張背後的備忘錄,想起你是誰。
和平回來了!

簡化流程的圖示說明:

【瀏覽器(顧客)】                 【伺服器(單人店長)】
       |                                          |
       |  1.「請讓我登入!」(ID/密碼)             |
       |----------------------------------------->|
       |                                          | (認證通過!)
       |                                          | ・建立背後備忘(Session)
       |                                          | ・發行兌換券編號(ID: 999)
       |                                          |
       |  2. 回傳「登入完成畫面」與「兌換券 999」     |
       |<-----------------------------------------|
(把 999 放入錢包 Cookie)                       |
       |                                          |
       |  3.「請給我我的個人頁面!」                |
       |     (同時出示錢包中的兌換券 999)         |
       |----------------------------------------->|
       |                                          | (喔!編號 999 呀,是那位客人!)
       |                                          | ・確認 999 的背後備忘
       |                                          | ・產生個人頁面的畫面
       |                                          |
       |  4. 回傳「個人頁面畫面」                    |
       |<-----------------------------------------|

所以才會仰賴「框架」

整理到這裡我心想:

「要做兌換券、每次比對編號、畫面還要一個個手工做……店長的負擔也太重了吧?」

沒錯。維持狀態(會話管理)與區分使用者這些事,真的非常麻煩。如果每次都從零手寫程式來做,簡直是苦行。

因此前人幫我們做好的就是 Web 應用框架(Web application framework)

框架把這些麻煩的「兌換券交換」與「後端雜務」等常用處理包裝好,提供給開發者使用。讓我們可以把時間用在「要做什麼好吃的牛丼(服務)」這個核心部分,而不是重複造輪子。

總結

我整理的理解如下:

  • HTTP 是會失憶的,如果放著不管就分不清誰是誰。

  • 因此伺服器會用「Cookie(兌換券)」和「Session(背後備忘)」來努力記住使用者。

  • 那些超級麻煩的後端雜務,可以交給 Web 框架來處理。

希望能讓你有「喔,原來是這樣啊!」的清爽感覺。

下次我想寫一篇進化到 SPA 的文章!


原文出處:https://qiita.com/wata-sho/items/34d20cd39006cce775d0


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝8   💬9   ❤️3
499
🥈
我愛JS
📝2   💬7   ❤️2
150
🥉
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登