在 AsiaYo 看見的改變

Graffine Wu
AsiaYo Engineering
Published in
9 min readJan 27, 2019

成長中的新創軟體公司,無時無刻不在生存與死亡的夾縫中努力戰鬥,為了快速進入市場,技術債的積累幾乎是每間公司的必要之惡。本文探討新創跨越 0到 1的階段後,如何重新盤點複雜的架構與商業邏輯,依照新的使用者規模打造新的系統架構,以及如何打破團隊的既有習慣,一起往成長的下一階段邁進。

各式各樣的道具藏在百寶袋裡

加入的第一個月

筆者約莫是在 2017/08 加入 AsiaYo,在加入前有耳聞 AsiaYo 的技術債累積十分驚人,當時心裡抱持著每間新創公司都有技術債的心態,覺得這應該不是什麼太大的問題便上工。剛進來的第一天我著實被某種無形的力量震撼到,那時的問題說穿了也很簡單,就是一些系統架構與資料庫的用法與我過去的經驗大相徑庭,作為一個小嫩嫩後端工程師有時百思不得其解為何某些資料是這樣子使用,也意識到若要全盤調整,應該至少需要兩三個季度才有辦法達成。於是我第一個月其實是有萌生退意的(被揍)。

危機就是轉機

轉念一想,系統健康檢查是件需要做的事情,健康檢查完接著就是針對各種標紅字的項目逐一改善,因此在這間公司大概是不太會有無聊的空間。以前的工作經驗大多是針對新產品或功能的系統架構設計,通常都沒什麼包袱需要考慮,設計起來也相對簡單。現在有機會重新設計一個線上產品的系統架構,對我來說是件有趣的事情。(敢情是喜歡被虐。)

同時兼顧舊有邏輯然後一邊重新設計老實說是件非常吃力不討好的事,除了要面對眾多陳年老 code,資料搬移或商業邏輯封裝都需要考慮各種可能(或沒想過)發生的情境。另外也不能因為系統重新設計就因此停擺了商業成長所需的功能,如何拿捏成長與技術債中間的平衡,就成了決策者最重要的課題。幸好 AsiaYo 在這方面給予技術團隊蠻大的支持,也因此讓這件表面上看起來對商業成長價值不高,但實際上對開發效率有重大影響的事情可以順利地往下走。

解問題的第一步

在解決任何問題前,我們需要先知道問題是什麼?(廢話。)

AsiaYo architecture — super old

上面這張圖是很早期 AsiaYo 的系統架構,在新創公司剛起步的階段,這是很常見的單站式 (Monolithic)架構。

AsiaYo architecture — old

上圖是在我加入前,AsiaYo 改版過一次的系統架構,時間點約莫是 2017–07 ~ 2017-11。在這個版本中可以看到幾個明顯的改變:

  1. 將單體式服務依照產品細分後拆分成不同的服務模組。
  2. Web 前後端分別導入軟體框架。
  3. 採用 Nginx 作為 load balance。單一服務開始可以形成服務群組。開始有機會做 non downtime 的系統變動。

這次的系統改版幾乎是重寫整個 AsiaYo 的服務,多虧了這次改版墊下了一部分基礎,讓後續的調整容易一點,在這個架構裡我們還可以看到幾個問題:

  1. 每個 user service 包含 payment 都可以直接與 database 溝通。資料面上沒有達到 single data flow 的最低要求。
  2. Load balance 採用 Nginx 單點式處理,尖峰流量時無法自動調節。
  3. Payment 處理金流相關功能,卻只有單點服務。
  4. 沒有 monitoring/alerting 機制,無法 predict 系統瓶頸以及正確告警。
  5. 沒有 log 機制(其實有些有,只是是用 database 實作),在查 issue 時需花費蠻大的力氣。
  6. 沒有 CI/CD 功能,產品 release 需要大量人工介入。

其他還有一些跟資料庫相關,但從這架構裡看不太出來的,包含:

  1. 資料庫正規化謬誤。
  2. 資料缺漏造成程式例外處理邏輯分散。
  3. 資料欄位命名過於奔放或者縮寫太多,可讀性低落。
  4. 資料表 index 設置不恰當,且完全沒有 FK。

有了問題,我們怎麼做?

先上一張目前的系統架構圖。下面再依序講解幾個較大的改變。

AsiaYo architecture — 2019–01–30

這張圖裡,黑線指的是一般使用者的流向,綠線則是指系統監控或者 log 資料的流向。

解決 CI/CD 問題

為何先處理 CI/CD 問題呢?主要是公司的產品其實尚未處於穩定的狀態,每週每天上新功能的頻率十分頻繁,而每次上版都需要人工處理,在這樣的前提下我們設計了一次 CI/CD 的流程,希望可以讓開發團隊更專心在開發功能本身,省去過多機械式的例行工作。詳細可參考筆者之前寫的用 Drone 打造 CI/CD flow

解決 log 問題

第二個想解決的是 log 問題,身為一個 RD,看 log 來 debug 是再正常不過的事情,早期 AsiaYo 都是將 log 放入 RDBMS 資料庫裡進行查詢,這種做法有兩個問題。

  1. log 的內容時常需要因情境變動,RDBMS 在欄位擴充上稍微麻煩一些。
  2. RDBMS 只能做到資料存放,但無法視覺化與分析,需要另外自行處理。

我們最後選擇了 ELK 這套工具。有了這個工具後,RD 在 debug 上終於可以擺脫 raw log 與一堆 shell script,改用 ELK 提供的各種視覺化圖形與統計方式來進行資料視覺化與分析。

Kibana

負載平衡,系統監控與告警

這三項與系統維運較為相關所以放在一起講。首先我們改用 AWS ALB 作為新的負載平衡服務,將負載平衡的 peak time 與 HA 問題交給 AWS 來處理。系統監控與告警的部份我們則是混用了 AWS 的 CloudWatch 以及自建的 Grafana + Promethus 。AWS CloudWatch 的部分多使用在機器本身的 CPU/Memory/IO 告警,由於筆者一直覺得 AWS CloudWatch 的介面不是太方便,在一些客製化的部分也較為侷限,所以與同事們討論後嘗試了 Grafana + Promethus 來做系統監控。

老實說我們目前尚無明確的結論決定何時該用 CloudWatch,何時該用 Grafana + Promethus,大體上 Grafana + Promethus 能提供一些更細緻的指標設定,客製化程度遠高於 CloudWatch,圖表的呈現上也較為直觀,跟各家雲端服務的整合性也很足夠,重點是有蠻多已經設定好的 template 可以直接套用,在佈建上是比 CloudWatch 快上許多的。

Grafana Dashboard

資料邏輯封裝

早期資料的寫入可以有多個不同的 entrypoints,這樣的架構最直接影響的是資料表的變動不易,另外是線上環境出問題時,我們需要到處翻查有問題的髒資料是從何處寫入,一來一往之間造成了 RD/QA 花費非常驚人的時間在釐清問題的根源,從而拖慢了開發的進度。

因此我們在 2018–05 做了一個較大的改變,也就是所謂的資料單一流向設計。我們抽了一層 DB application layer 負責處理上層應用者服務與資料庫之間的溝通,最高的指導原則是一份資料只能由一個服務來處理如何流進與流出。

我們花了大約一個半月的時間完成此服務的基礎建設,包含 code architecture 遵循 Clean Code 與 SOLID 原則設計,加入 unit testing,設計 log 架構等等,之後我們逐步重新設計各項 web api,將資料處理邏輯慢慢從上層應用者服務轉移至此 layer。

這部分是這次 AsiaYo 架構改變最辛苦的一個工程,直至今日 (2019–01)尚未全部完成,我們還需要再持續不斷的優化。

工程問題之外…

組織架構調整

早期 AsiaYo 的產品團隊是依照產品分 team,各 team 的資源包含 PM/RD/QA 都是獨立運用,也各自有不同的商業指標需要負責。實際上,在這樣細化分工的體制下, AsiaYo 在資源運用上產生了一些問題,各自的 team 過於專注在自己 team 內的事務,產生了很嚴重的穀倉效應 (Silo Effect),這在 AsiaYo 這樣的新創公司是一個蠻致命的問題。

因此我們在組織架構上做了一些改變,將各自的穀倉推倒,把 team 改制成以 role 來區分,也就是一般 web 開發常見的 PM/Frontend/Backend/QA/SRE ,每一個角色都是一個共用的池子,團隊決定該執行的專案內容,然後由主要的 owner 負責進池子抓取可使用的資源。這樣的調整可以讓資源協調發生在產品規劃的早期階段,讓團隊聚焦在有商業價值的功能,並且在決定專案內容後快速地產出。

溝通,理解,再溝通,再理解

在改變的過程中,很容易會遇到來自四面八方不同的阻力,比方說:

  1. 系統架構調整沒有商業價值,為何要投入?
  2. 我的 team 運作得蠻好的,為何需要重新調整?
  3. 老闆不理解架構調整對開發效率會有多巨大的轉變,該如何說服老闆採納意見?
  4. Code 改成新的寫法跟新的規範很麻煩,能不碰就不碰。
  5. (下略三千八百萬條…)

這類問題其實都很正常,每次改變伴隨著的是每次的重新習慣,一定會有適應與不適應的狀況發生,遇到這類問題其實就是不斷的溝通與理解,確保團隊成員都在同一個溝通的水平上,這說起來很簡單,但執行上卻是異常地困難,如何做到,考驗著決策者的智慧與手腕。

小結

AsiaYo 的文化有兩個重點, Voice 以及 Transparency。在這裡每個人都可以充分表達自己的聲音,不管是對產品的想像與建議,或是任何事務或流程上覺得可以改進的地方。我們最怕的不是溝通遇到問題,而是不願意進行溝通。

老實說,這整個改變的過程是一件相當累人的事情,需要不斷地與不同的人進行溝通協調,若有下次,筆者也不知道會不會願意再走一次相同的路。但每次看見某些改變過程中累積的能量可以在不經意的時刻幫助到團隊,就會覺得過去的辛苦是值得的。

就這樣,我們下次見。若你/妳對 AsiaYo 有興趣,歡迎與我聯絡或從下方連結與我們接觸。

職缺連結

--

--

Graffine Wu
AsiaYo Engineering

Senior backend engineer at AsiaYo. Interested in system architecture and VIM.