API的Critical session

開發App的時候候,如果要取得server端的資料,通常就必須透過呼叫API的方式來進行,前陣子在開發時碰到一個critical session的問題,我們遇到的狀況是這樣的:

  • 某個App需要取得server端記錄的使用者id、App的功能、最新消息…等資訊,。
  • 此App在呼叫API時,會將行動裝置的device unique id傳送到server端,用來辨識不同的對象,並回傳使用者的id。
  • Server端接收到device unique id後,會記錄到資料庫中;若是從未出現過的裝置,就要新增一筆紀錄,並將產生的使用者id回傳給App。

從這個需求來看,Server端收到API呼叫時,要作以下的處理:

  • 檢查收到的device unique id是否存在於資料庫中 (步驟A)
    • 若存在,讀取使用者的id。 (步驟A-1)
    • 若不存在,新增一筆使用者資料,並取得新增後的使用者id。 (步驟A-2)
  • 將使用者id與查詢的資料打包回傳給App (步驟B)

簡單的程序,對吧?錯了!!!

問題就發生在App啟動的同時,可能一次發出了多筆API呼叫,於是上面這個程序就有可能同時開始進行,實際碰到的情形是這樣的:

  1. App同時呼叫了2個API(API-1與API-2)
  2. 2個API同時進行上面的步驟A,查詢device unique id是否存在?
    • 結果2個 API取得的結果都是:使用者不存在,進行步驟A-2
    • 因為device unique id欄位設定了唯一鍵(unique),因此2個API只有一個成功在資料庫中新增了資料,另一個則失敗
  3. 結果:
    • 一個API正常回傳了使用者的id,和查詢的結果。
    • 另一個API因為查不到使用者id,又無法透過新增資料取得新使用者id,而回傳系統層級的錯誤訊息。

最後,App當然就很慘地在某些情況下掛掉了,而且要命的,是Critical session並不是每次都發生,於是,花費了不少額外的時間debug…

如何避免這個問題?首先第一件事當然是在資料表的欄位上,一定要設定唯一鍵(unique),以免建立了不必要的、相同的資料,然後呼叫、檢查的程序,可以改成這樣:

  • 以收到的device qnique id直接嘗試在資料庫中新增一筆資料,並檢查新增結果:
    • 若成功,表示這個使用者是新使用者,讀取新增後的使用者的id。
    • 若新增失敗,表示資料庫中已有此使用者的資料,讀取使用者id。
  • 將使用者id與查詢的資料打包回傳給App (步驟B)

搞定~下課!從此App與Server過著幸福快樂的生活…(希望啦~只是他們的生活總是充滿了"驚喜"…身為工程師的你,一定懂的~)

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *