# 天瀚國際科技 後端工程師技術問卷 (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 解析階段

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
];
}
```