# 天瀚國際科技 後端工程師技術問卷 (20210114) ## 1. 請問您目前主要的技術學習管道為何?(例:某網站,特定書籍等) github,udemy,biibii,google ## 2. 請舉例在你過去的工作經驗中,覺得面臨過最大的技術挑戰或最令你印象深刻的技術性問題,並分享最後如何解決他? - 某情境設計下 每一User 會建立各自sqlite , 當使用者數量過多時,讀寫產生異常 - 橫向擴展磁碟數量,增加IOPS , 將不同User sqlite 分別存儲不同區域磁碟 - 將每區域的User sqlite 以資料夾分門別類 ,改善查詢至使用者sqlite時間 - 當個別使用者sqlite db 多個程序同時讀取 會有write-lock,資料需另做處理 ## 3. 當 Client 端存取 https://foo.com/api/v1/bar 這個 HTTP API 的位置,請從 DNS 解析到 PHP 解析到最後回傳 Response 內容盡可能完整描述中間所有詳細發生的流程。(以 Nginx + PHP-FPM 的架構為例) ### - DNS 解析階段 ![](https://i.imgur.com/carkSbk.png) 1. 查詢主機hosts文件是否存在domain對應ip,有則返回 2. 根據DNS設定 ,向其發起查詢 3. 查詢是否有緩存 有則返回 4. 向根服務器查詢`.com` 服務器ip 5. .com服務器 取得該domain 所對應ip位置 6. dns服務器返回其domain ip位置 7. 與server 進行連線 ### - Nginx + PHP-FPM 連現階段 - TCP 建立三向握手 - FastCGI master監聽 port, 接收 request 交由某一worker執行 - 建立https連線 - Client 發送TLS版本+加密集資訊+隨機數 - Server端 選用雙方共同支援版本及密碼集+隨機數,同時將證書及公鑰回傳 - Client 也信任該憑證認證機構,並驗證其證書是否合法,不合法則提出警告 - Client 創建一個隨機私鑰並用server端公鑰進行加密 - Server 端利用私鑰解密後獲取隨機私鑰+雙方隨機數組成會話私鑰 - 雙方利用會話私鑰加密發送訊息 , 確認服務正常 , https連線建立 - nginx 配置解析 - location , 比對請求 執行root 所設定位置php程式 - fast-cgi 將請求拋轉至 php-fpm執行 - PHP解析器執行程式碼 route處理 `api/v1/bar` 並返回結果 - 釋放worker - 連線結束 TCP 四次揮手 ## 4. 如下有一個票券購買的範例程式,程式會先檢查票券的剩餘數量,若數量足夠則進行票券購買流程並且扣除票券剩餘數量,若票券數量不足則會拋出例外錯誤。請問以下的程式可能存在什麼問題,如果是你會怎麼修改? - ex : 當A和B瞬間購票行為 兩者都是取到相同票券剩餘數量1000 結果相互執行-1的動作 2筆update記錄為999 正確情況應該為 一筆999, 另一筆998 - A拿到票券剩餘數量資源時 此資源應當處於被鎖定狀態 當A完成update資料時才會釋放資源 然後讓B繼續存取 否則B必須等待A完成釋放資源 ``` public function buyTicket(Request $request, Ticket $tickets) { // 1.開始交易 DB::beginTransaction(); try { // 2.查詢時進行上鎖 $ticket = Ticket::lockForUpdate()->find($tickets->Id); // 3.檢查票券是否還有足夠數量 if ($ticket->available_amount <= 0) { throw new TicketUnavailableException('Ticket amount is not available'); } // 4.中間購買邏輯省略 // 5.扣除票券剩餘數量(尚未提交) $ticket->update([ 'available_number' => $ticket->available_amount - 1; ]); }catch (\Exception $e) { DB::rollback(); throw new TicketUnavailableException('Error:' + $e->getMessage()); } // 6.提交結果 DB::commit(); return [ 'success' => true ]; } ```