# 作品集 可利用 HackMD 左側的目錄來瀏覽各個專案, 每個專案內會有部分的功能示意圖, 以及重點功能解說 ## # 好玩專案 - 開發工具: Laravel - 資料庫: AWS RDS - 機器: AWS EC2 - Cache: AWS ElastiCache - Queue: AWS SQS - 使用了其他多種 AWS cloud service 這個服務的核心在於, 公司 or 個人可以跟服務購買活動, 然後使用者可以在活動內與主持人互動 情境: 鴻海向服務購買了一個活動來當作他們尾牙的互動方式, 於活動期間, 鴻海的員工可以透過 APP 登入並參加該活動, 然後主持人與員工可以在聊天室內即時互動, 並且可透過各種遊戲, 例如抽獎, 搶紅包, 大樂透, 有獎徵答等等的與員工互動, 炒熱氣氛 ![](https://i.imgur.com/wBGs4EM.png) ![](https://i.imgur.com/VLivfQg.png) ![](https://i.imgur.com/Z2WZ1Vy.jpg) ![](https://i.imgur.com/uZ8dhBo.png) ![](https://i.imgur.com/vnvohRW.png) ![](https://i.imgur.com/6lrSyTr.png) ![](https://i.imgur.com/2KJzjeD.png) ![](https://i.imgur.com/hugaBck.png) ![](https://i.imgur.com/Yk9kQqJ.png) ![](https://i.imgur.com/Isdof3B.png) ![](https://i.imgur.com/PGKdtJw.png) ![](https://i.imgur.com/bx1EV9W.png) ### # 批量匯入 這個需求會需要透過 excel 來批量匯入員工, 以及 zip 來批量匯入相對應員工的照片。 這個匯入的動作是相當耗時的, 因為可能一個 Excel 中會有成千上萬筆資料, 或是一個 zip 檔案中可能會有上千張圖片。 所以這邊是採用 queue 的方式, 讓管理者們把檔案上傳後, 後端再非即時的處理匯入的任務, 這樣的做法可以大幅的提升使用者體驗, 使用者只需把檔案上傳, 然後使用者就可以去做其他的事了, 上傳之後機器會把任務排隊排起來, 然後慢慢的去執行這些任務, 算是用時間來節省成本, 將一些高耗資源但是沒有急迫性的任務排隊慢慢的處理。 並且, 在匯入的同時會先把匯入功能鎖住, 避免管理者重複的匯入, 造成不必要的效能浪費。 ![](https://i.imgur.com/FmKJbxD.png) ![](https://i.imgur.com/0nXoym9.png) ![](https://i.imgur.com/UrnbpIg.png) ### # 搶紅包 這個服務比較特別的地方在於某些大公司的員工比較多, 可能會有上千個甚至數千的, 而搶紅包這樣的遊戲會在瞬間產生非常大量的 request, 為了避免 server 爆掉, 我們讓前端直接向 AWS SQS 發 reqeust, 而後端 server 異步的從 SQS pick up request 來執行, 當 pick up 的數量到達搶紅包的名額時, 就 broadcast 給有中獎 & 沒中獎的使用者 在搶紅包開始與結束, 都把 SQS 整個清掉, 確保不會有人惡意偷跑的情況 ### # 架構 儘管解決了瞬時的高流量問題, 但上千人同時在線連發 request 依舊不是一台 server 扛得住的 因此, 我們使用了以下的服務來承載流量 - 使用 AWS 的 Load Balancer, 並且使用 Auto Scalling policy 來擴縮機器的數量, 由於這個服務本身的特性, 只會在某些特別區間才會有高流量, 因此我們將 auto scalling policy 設定好, 可以讓客戶一鍵的去擴縮機器的數量 - 我們使用 s3 來 host 前端的部分, 並且在前面掛上 CDN 服務 CloudFront, 當專案有更新時在 invalidate 原先的 cache - 我們使用 Redis 來 cache 一些不常變動的資料, 盡可能減少 DB operatoin - 我們使用了 system manager 來將 .env 統一管理, 這樣不管是新啟動的機器或是正在運行的機器都統一的使用一份 .env - 我們使用了 CloudWatch 來統一管理所有的 log, 因為每一台機器都可能處理 request, 且可能隨時會關閉 ![](https://i.imgur.com/mfMoq4f.png) </br> ## # EchossVIP 是一款結合了實體店家電子印章, LINE 延伸應用的服務 - 整個專案都是使用 PHP 框架 Laravel 開發的 - 資料庫為 AWS MySQL - Cache 為 redis 以及 APC - 機器為 AWS EC2 運作情境, 使用者到了星巴克消費, 透過星巴克的 QRCode 導向服務註冊頁面, 透過 LINE 第三方登入的方式成為了星巴克品牌的客戶, 之後便可以收到來自於星巴克的各種延伸 LINE 服務, 比如: - 消費滿額, 星巴克透過 LINE 寄送優惠卷 - 發送星巴克的促銷活動連結 - 功能很多就不一一列舉, 概念有描述清楚即可 ### # 登入頁 如上所述, 服務主要支援三種使用者對象登入 - 服務管理者 - 品牌管理者 - 品牌下的使用者 (LINE 登入) ![](https://i.imgur.com/Hccp0ns.png) ![](https://i.imgur.com/4U1fOS8.png) ![](https://i.imgur.com/688ga80.png) ![](https://i.imgur.com/oLL0o3R.png) ### # 主要功能頁面 挺多功能的, 不過這個專案是多人協作的, 下面會針對一些我個人實作且我覺得比較有趣的地方特別說明 ![](https://i.imgur.com/oGWM5Rk.png) ### # 會員卡模組 這邊的資料結構比較特別, 因為不同等級的會員卡具有上下相依的關係, 比如等級一的會員卡最高金額肯定要小於等級二會員卡的最低金額, 還有其他的類似限制 但同時會員卡又必須支援 CRUD, 例如我刪除了 level 2, level 1 跟 level 3 的上下限金額必須自動連接起來, 且 level 3 必須變成 level 2, 又或者我更新了某張卡片的上下限金額, 這個更新要連動到相鄰的卡片, 這樣金額才不會有斷差 要達成這樣的需求, 這邊是使用 linked list 資料結構, 在 DB 記住 next, previous, 再實作相對應的 linked list CRUD ![](https://i.imgur.com/gsEJhpk.png) ### # 匯出模組 這裡會需要將所有使用者的資料匯出成 CSV, 因為某些品牌下的使用者高達數萬, 且需匯出的資料橫跨了多張 table, 算是會比較耗時的動作 因此這邊後端使用了 Queue 異步來處理, 品牌管理者提交了匯出請求後, 我先產生該 job 並 pass 到 redis queue, 然後限制 worker 的最大數量, 依序地處理匯出, 將資料 chunk 並匯出成 csv 檔, 然後再將 csv 檔上傳到 s3 在異步匯出的同時, 會先把該功能鎖住, 避免品牌管理者重複多次的匯出, 待匯出任務完成後, 才能再次執行匯出 成功匯出並上傳到 s3 的檔案, 會顯示在下載區供管理者下載 ![](https://i.imgur.com/95b30WI.jpg) ![](https://i.imgur.com/S2ZAbEC.png) ### # 持續部署 部署管道中沒有測試, 但有做持續部署 這邊部署比較特別的地方, 是實作了 Laravel Envoyer 的概念, 簡單來說, 會先把新的 commit pull 下來, 準備就緒後, 在 soft link 過去, 盡可能的達成 zero downtime storage 是共用的, current 代表最新的 commit version, release dir 中有 previous version, current 會對應到 release dir 中的 newest version ![](https://i.imgur.com/2JzrOes.png) <br> ## # 日日考核 這款服務的核心應用, 是可以讓不同的公司給他們所屬的員工評分, 評分的依據來自於員工的學歷, 年資, 以及主管的給分 - 開發工具 Express - 資料庫 GCP Cloud SQL - 機器 GCP Compute Engine ![](https://i.imgur.com/C0BZsMr.png) ![](https://i.imgur.com/acs1XOM.png) ![](https://i.imgur.com/NYqomtl.png) ### # 爬蟲 這邊去爬了政府財政部的資料, 並串接其他服務來解掉驗證碼 ![](https://i.imgur.com/cpwAKUj.png) ### # 員工編號 這邊有個比較有趣的需求, 員工編號必須要不間斷, 不跳號, 除非某個員工被刪除了, 那跳號無可避免, 但在新增員工時必須不跳號 這裡目前是使用悲觀鎖來解決 race condition 的問題, 但其實也可以使用樂觀鎖來解決, 這樣效能更佳, 雖然還是會有機率產生 race condition, 但只要在 transaction 的最後一個 operation 判斷員工編號有沒有變動過, 有變動過則該次 transaction 失效, 沒變動過則 commit, 這樣可以更加降低 race condition 的機率, 但就可以不使用 lock, 盡可能地避免 dead lock, 節省 CPU cost ![](https://i.imgur.com/HmhucND.png) ### # 無限階層架構 這邊比較特別的, 是每個部門都可以有無限的子部門一直往下延伸 這邊是使用一個 string column `chain`, 用空間複雜度來降低時間複雜度, 比如說, a 部門的 id 是 1, b 部門的 id 是 2, c 部門的 id 是 3, 而 a, b, c 是一直往下延伸的父子關係, 那 a 的`chain` column 會是 null, 因為他沒有 parent, b 的 chain column 會是 `-1-`, 而 c 的 chain column 會是 `-1-2-` 透過這樣一個欄位, 可以直接取得特定部門的所有 parent, 以及 children 當然, 使用 tree structure 也是一個方法, 但考量到在 update or insert 的時候, 可能會需要 update 多個不必要的 row (left & right), 所以在此情境下, 使用一個 string column 可以省下相當多不必要的 DB operation ![](https://i.imgur.com/8vx11uo.png) <br> ## # Echo Square 一款結合空間與互動的應用 情境: 使用者可以指定以自身為基準的半徑範圍, 然後發送訊息, 任何在這個範圍內的 APP 使用者都會收到這則訊息 發送訊息會耗體, 體力每五分鐘回復 - Laravel 實作 - 資料庫 MySQL - 機器為 Forge 搭配 AWS EC2 ![](https://i.imgur.com/VqtoMCN.jpg) ![](https://i.imgur.com/usT9fd3.jpg) ### # MySQL 空間函數 實作時發現 MySQL 的 st_distance 函數有一些限制, 在這個情境中並無法使用到 index, 可能會產生效能問題, 因此做了一些研究後, 自己寫了公式來求得結果, 效能是比直接使用 st_distance 更佳的 ### # 測試 此專案皆使用 TDD 開發, 先把邏輯理清, 寫下測試, 再實作邏輯 ### # 部署 此專案使用 GitLab Runner 來實作 CI/CD 部署, 測試的部分是先將 Laravel 環境製作成 docker image, 並直接在部署過程中使用