2020/05/08

Preserving State in DataSnap REST Server



DataSnap REST Server 有儲存狀態的能力,這取決在LifeCycle的設定值。

DataSnap REST Server 儲存狀態方式一:LifeCycle

LifeCycle 的【狀態範圍】在TDSServerClass實例(Class Instance);有 Server, Session(Default), Invocation 三種,影響 TDSServerClass 實例(class instance) 的生命週期。

  • Server:WebServer建立後即會建立一個TDSServerClass實例(class instance)。Server關閉時釋放之。(有狀態 = 全域變數)
  • Session:Session建立時建立一個TDSServerClass實例(class instance)。觸發OnDisconnect時會釋放之,以下兩種條件會觸發:
    • TSQLConnection.Close (TCP 長連接。有狀態 = 僅配對該Session)
    • REST Request 請求結束 (HTTP 的短連接,無狀態)
  • Invocation:同Session建立方式,不同之處在 TCP/HTTP Resquest 請求結束後會強制觸發OnDisconnect事件,釋放TDSServerClass實例(class instance)。

比較妙的地方是 LifeCycle 如果沒有正確走到 OnDisconnect 事件時,TDSServerClass 實例會一直佔在記憶體中無法被釋放,造成 Memory Leak 現象。
然而使用 REST Client (HTTP Request) 卻不會出現此問題 。

也就是使用TSQLConnection為主的場合,WebServer 要定時重新啟動,以釋出那些【潛在異常】的TDSServerClass 實例。

TSQLConnection有LifeCycle可以儲存狀態,而REST Client(含 JavaScript Ajax)卻看得到吃不到,就沒有儲存狀態的方式嗎?



古書曾說:上帝關了一扇窗,必定會開一道門 (並沒有)


DataSnap REST Server 儲存狀態方式二:Session Management

DataSnap REST Server 有個標準配備:Session Management。可以透過它來做到對應 Session 級的狀態管理。

TDSSession.HasData/PutData/GetData 是基本配備,可以自定Key-Value的方式來管理 Session Data。

而在 XE2 之後更提供了 HasObject/PutObject/GetObject,值得一提的是 GetObject 回傳的是物件定址,在開發上可以減少約20%傳值的程式碼!

但也因為 Session Management 的關係,間接提高增設平衡負載(Load balance)的難度。

結語

瞭解datasnap框架兩種狀態管理的邊界範圍與生命週期,框架內建的session management看似會成為【有狀態的服務】而造成效能瓶頸。

事實上LifeCycle為Session和Invocation時,REST Client都不會讓DataSnap保存TDSServerClass實例,那麼也可以讓每一次request產出新的session ID,至於狀態則可存在method參數裡面,少了對session management的依賴,就能達成真正的無狀態,要做平衡負載也是一件簡單的事情了!

SessionID也可以在每次服務結束就釋放,或減少session timeout的時間,以降低多人連線時session management記憶體負載。

同場加映 FormatResult in JSON Method Result

DataSnap REST Server 裡所有的 Method 回傳的格式都會帶一個屬性為【result】的物件 (例:{"result":[0]})。

在不改動 Delphi RTL Source 下也是可以完成自定義工作。

以 EchoString 為例:


就是這麼簡單,也不用再管 Result 要回傳什麼了!


以上資訊分享給大家。我們下次見。

See also

LifeCycle

FormatResult

沒有留言:

張貼留言