一起學系統架構 - Asynchronism

tags: 系統架構

以下的原文取自 scalability for dummies 系列,並附上對照翻譯。

原文

This 4th part of the series starts with a picture:
這個系列的第四章,讓我們始於一個情境:

please imagine that you want to buy bread at your favorite bakery.
想像一下你正要去你最喜歡的麵包店買麵包。

So you go into the bakery, ask for a loaf of bread, but there is no bread there!
你到了麵包店想買一條麵包,但他們目前還沒有做好任何一條麵包!

Instead, you are asked to come back in 2 hours when your ordered bread is ready.
他們跟你說兩小時之後等麵包做好了再回來拿。

That's annoying, isn't it?
這超惱人的不是嗎?

To avoid such a "please wait a while" - situation, asynchronism needs to be done.
為了避免這類 "等一會" 的情形,就必須用到非同步。

And what's good for a bakery, is maybe also good for your web service or web app.
這不只是有利於麵包店,它同時也利於我們的網路服務或網路應用程式。

In general, there are two ways / paradigms asynchronism can be done.
一般來說,大概有兩種非同步執行可以應用。

Async #1

Let's stay in the former bakery picture.
我們一樣用前面麵包店的例子。

The first way of async processing is the "bake the breads at night and sell them in the morning" way.
第一個非同步處理方法是 "麵包店在晚上先做好麵包,然後在早上賣"。

No waiting time at the cash register and a happy customer.
收銀員跟開心的客戶,沒有人需要等待。

Referring to a wep app this means doing the time-consuming work in advance and serving the finished work with a low request time.
對應到網頁應用程式就是,預先處理很耗時工作讓我們只需要少量的請求時間拿到最後結果。

Very often this paradigm is used to turn dynamic content into static content.
這個模式曾經很常被用來將動態的內容轉換成靜態內容。

Pages of a website, maybe built with a massive framework or CMS, are pre-rendered and locally stored as static HTML files on every change.
網站的頁面,可能先由重量級的框架或CMS建構, 並每次異動都會預先渲染並儲存靜態 HTML 檔案。

Often these computing tasks are done on a regular basis,
這些運算任務通常是定期執行,

maybe by a script which is called every hour by a cronjob.
像是使用 cronjob 每個小時執行一個腳本。

This pre-computing of overall general data can extremely improve websites and web apps and makes them very scalable and performant.
這類整體數據預運算可以大量提升網站跟網頁應用的擴展性跟效能。

Just imagine the scalability of your website if the script would upload these pre-rendered HTML page to AWS S3 or Cloudfront or another Content Delivery Network!
試著想像一下, 如果有個腳本可以將預渲染的 HTML 頁面上傳到 AWS S3 或是 Cloudfront 或其他的內容傳遞網路, 你的網站的擴展性會有多好。

Your website would be super responsive and could handle millions of visitors per hour!
你的網站會具備超強的響應能力,並且可以處理一小時上百萬個訪問量。

Async #2

Back to the bakery.
回到麵包店的例子。

Unfortunately, sometimes customers has special requests
不幸的是,有時候顧客會有特殊要求,

like a birthday cake with "Happy Birthday, Steve!" on it.
像是一個生日蛋糕上有 "生日快樂,Steve!" 的字。

The bakery can not foresee these kind of customer wishes,
麵包店不可能預知這個客戶需求,

so it must start the task when the customer is in the bakery
所以只能客戶出現在麵包店它才能開始這個任務,

and tell him to come back at the next day.
並讓顧客明天來拿。

Refering to a web service that means to handle tasks asynchronously.
類比到網路服務就是我們要做非同步的任務處理。

Here is a typical workflow:
以下是典型流程:

A user comes to your website and starts a very computing intensive task which would take several minutes to finish.
一個用戶到了你的網站,並執行一段非常吃運算的任務需要花好幾分鐘才能完成。

So the frontend of your website sends a job onto a job queue
所以前端網頁發送了一個任務到任務佇列,

and immediately signals back to the user:
並立即回覆一個訊號回覆用戶:

your job is in work, please continue to the browse the page.
你的任務正在進行中,請繼續瀏覽頁面。

The job queue is constantly checked by a bunch of workers for new jobs.
會有一堆工作行程會持續關注任務佇列,

If there is a new job then the worker does the job
如果有新的任務,工作行程就會處理那個任務,

and after some minutes sends a signal that the job was done.
並在數分鐘後發送一個訊號告知任務已經完成。

The frontend, which constantly checks for new "job is done" - signals,
前端,它會持續信號檢查任務是否完成,

sees that the job was done and informs the user about it.
如果看到任務已經完成,它就會讓用戶知道。

I know, that was a very simplified example.
我知道,這是過於簡單的範例。

if you now want to dive more into the details and actual technical design,
如果你想要深入了解更多細節與實際的技術設計,

I recommend you take a look at the first 3 tutorials on the RabbitMQ website.
我推薦你可以去看 RabbitMQ 網站前三個教程。

RabbitMQ is one of many systems which help to implement async processing.
RabbitMQ 是其中一種幫助我們實作非同步處理的系統。

You could also use ActiveMQ or a simple Redis list.
你也可以用 ActiveMQ 或是 簡單用 Redis 的 list。

The basic idea is to have a queue of tasks or jobs that a worker can process.
概念上就是用一個任務佇列讓工作者行程可以去拿任務。

Asynchronism seems complicated,
非同步看起來很複雜,

but it is definitely worth your time to learn about it and implement it yourself.
但他絕對值得我們花時間去學習並實作他。

Backends become nearly infinitely scalable
它讓後端擁有近乎無限的擴展性,

and frontends become snappy which is good for the overrall user experience.
前端也能提供更佳好的整體用戶體驗。

If you do something time-consuming, try to do it always asynchronously.
每當你想要執行耗時的任務永遠試著讓它非同步。

Did you find this article valuable?

Support Hello Kayac by becoming a sponsor. Any amount is appreciated!