[訊息論壇] ICE Messaging
Forum 蔣居裕
<技術篇> 新世代訊息技術深度剖析 ─ 細說
iPush® Server V2 (下)
再一次把 iPush® V2 訊息通訊層級基本圖擺陣出來,以方便讀者理解我們的說明:
| 
|
| 圖一、iPush®
V2 訊息通訊層級基本圖 |
文字顏色說明
紫紅:為
iPush® V2 新增之特性功能。
藍色:為 iPush®
V1.x 已有之特性功能,但 V2 又加以修改延伸。
黑色:為 iPush® V1.x、V2 所共同擁有之特性功能。
上週我們已經由下而上,說明了網路通訊協定、訊息傳遞模式、訊息定址方式這三層,本週說明將再上兩層。
| 4. 訊息安全保護 (Message
Security) |
Pack
/ Unpack:適用在 Channel 訊息傳遞加密 / 解密
Scrambling:適用在 Subject 訊息傳遞加密 / 解密
訊息在傳送的過程當中,無論是傳送端到 iPush® Server,還是
iPush® Server 到接收端,都有加密/解密的機制,來保護訊息的安全,也就是做到訊息內容的隱密性。
<Channel 訊息加密/解密>
在 iPush® V1.x 中,Developer 可分別使用
API 中的 PackData() 與
Unpackdata() 函式呼叫來為傳送與接收的訊息進行加密與解密的動作。但是到了
iPush® V2,我們有了以下的改變:
ActiveX API
不再使用函式呼叫,改用屬性 (Properties) 的設定。也就是在使用 XiPush2.ocx
時,先設定 Property packChannelData
(Boolean,預設為 True)。
若其值為 True,則 API 在將訊息送給 iPush®
Server 前,會自動為訊息加密;相對的,若 API 接收到從 iPush®
Server 推播過來的訊息後,也會自動為訊息解密,再送給應用程式處理。
若其值為 False,則無論是傳送還是接收訊息,API 都不會進行加密、解密的動作。
由於 Packing 的作業除了安全性考量之外,還包含訊息內容的相容性編碼處理,所以我們強烈建議您一定要將其設為
True。
Java Class API
在 Class iPush2Link 中改用 ipushSetPackChannelData(int
index, boolean dopack) 函式呼叫,其中第二個參數 dopack 為 boolean 值。
若 dopack 值為 true,則 API 在將訊息送給 iPush®
Server 前,會自動為訊息加密;相對的,若 API 接收到從 iPush®
Server 推播過來的訊息後,也會自動為訊息解密,再送給應用程式處理。若您不叫用 ipushSetPackChannelData(),在預設情況下,API
會自動進行訊息的加密、解密。
若 dopack 值為 false,則無論是傳送還是接收訊息,API 都不會進行加密、解密的動作。
同樣的,我們強烈建議您最好為 Channel 訊息進行加密、解密。
<Subject 訊息加密/解密> 對 Subject 訊息的加密/解密作業,稱為
Subject Scrambling。
在 iPush® V2 中,我們為 Subject 訊息增加了許多新的屬性,這在稍後會提到。因為要對這些新增特性進行包裹,所以對於
Subject 訊息,無論是 API 到 iPush® Server,還是 iPush®
Server 到 API,都會在網路傳輸時,強迫進行加密、解密。
對 Subject Scrambling,是容不得 Developer 置喙的。即 API 不提供任何函式呼叫,或是任何屬性設定項目可讓您使用,一切都由系統自動進行。
| 5. 訊息屬性 (Message
Attribute) |
Channel
/ Subject 訊息共有屬性:Message Priority
Subject 訊息屬性:Persistent/Non-persistent、QoS、Time-To-Live、Connection
ID、Message ID
我們已經多次提到,iPush®
V2 為 Subject 訊息增加了許多新的屬性,總合起來,包含了:
-
Persistent/Non-persistent
-
QoS (Quality of
Service)
-
Message Priority
-
Time-To-Live (TTL)
-
Connection ID
-
Message ID
在 API 的呈現上,以上六個訊息屬性有不太一樣的運作方式,請特別注意下列說明:
-
其中的 Message Priority,其實也是
iPush® V2 Kernel 對 Channel 訊息的新增屬性,但因為向下相容的考量,我們並未實作在
API 中。
-
一個 Subject 訊息究竟是屬於 Persistent
還是 Non-persistent?是訊息發送者藉由呼叫的函式種類來決定的。
-
QoS 與 Message Priority 用於訊息擁塞處理,由
Subject 訊息發送者在訊息發送的函式呼叫中以參數方式指定之,如 ipushSendNPSubjectData()、
ipushSendPSubjectData()、
ipushSendNPQueueSubjectData()、
ipushSendPQueueSubjectData()。
-
Time-To-Live 用來指定一個 Persistent
訊息在系統中的有效期限,由 Subject 訊息發送者在 Persistent 訊息發送的函式呼叫中以參數方式指定之,如
ipushSendPSubjectData()、ipushSendPQueueSubjectData()。
-
Connection ID 與 Message ID
會由 iPush® Server 透過 ActiveX Event SetSubjectData()
或 Java interface iPush2MsgListener 中的 Method
onSubjectMessage()
告知接收者。Connection ID 的值為該 Subject 訊息的發送者連線編號,Message
ID 為該 Subject 訊息的編號,這兩者皆由 iPush® Server
自動賦予。
新增這些訊息屬性的目的,無非是要達到:
以下就來詳述這六個訊息屬性的特性與 API 運用方式。
<Persistent/Non-persistent>
由叫用的發送函式來決定一個 Subject 訊息是
Persistent 還是 Non-persistent
Persistent 可翻譯為 "持續性";Non-persistent
即為 "非持續性"。在 iPush® V2 中,一個 Subject
訊息,不管它是在 Pub/Sub,還是 P2P 模式下傳遞,它就只能是一個 Persistent 或是 Non-persistent
訊息;在這屬性上,非 "P" 即 "NP",沒別的好說。
理論上,被標示了「Persistent」的訊息,就一定會被送達訂閱者的手中。這是如何做到的呢?
若發送者叫用了 ipushSendPSubjectData()
或是 ipushSendPQueueSubjectData(),則
API 就會將該訊息加上「Persistent」的標頭 (header),然後傳給 iPush®
Server。當 iPush® Server 接收到含有「Persistent」標頭的訊息時,就會先會其儲存起來,然後再向發送者發出回應
(Acknowledgement, Ack) 以示收到。
這樣的 Persistent 作業方式,是訊息保證送達 (Guaranteed Delivery)
非常重要的達成要件之一。
我們下期會專門針對訊息保證送達來詳細說明。
相對的,若是發送者叫用 ipushSendNPSubjectData()
或 ipushSendNPQueueSubjectData(),則
API 就會將該訊息加上「Non-persistent」的標頭 (header),然後傳給 iPush®
Server。當 iPush® Server 接收到含有「Non-persistent」標頭的訊息時,也一樣會將其儲存起來,然後給發送者一個回應,以示收到。
嗨!這位作者先生,怎麼 Persistent 跟 Non-persistent 訊息的處理看起來都差不多呢?
是的,截至目前為止,都差不多,對 iPush® Server
來說,差別只在它收到並儲存的是一個「Persistent」還是「Non-persistent」Subject 訊息。但後續送給訂閱者的處理,就會依此,而有較大的差異了。我們一樣在下期中說明。
<QoS>
由叫用發送函式中給定的 qos
參數值來決定一個 Subject 訊息的 QoS 等級
iPush® Server 可以同時處理成千上萬筆的訊息,如果每一筆訊息都只按它被
iPush® Server 接收的前後順序排列,先到先發而不顧其內容的重要性,那麼當系統擁塞時,一些關鍵的訊息,不就無法被及時轉遞出去了嗎?
有鑑於此,新一代的 iPush® V2 智慧型訊息伺服器添加了
QoS 機制,來做為提昇訊息傳遞整體服務品質的一種手段。QoS 的全名為 Quality of Service,翻成中文為
"服務品質",意涵是發送者可以指定一個 Subject 訊息的品質等級。
QoS 等級從 0 ~ 3,共 4 級,數字越大,品質等級越高。
對於每一個訂閱接收者而言,系統會為其建立並維護專屬的訊息待發區 (Message Buffer),若該訊息待發區出現壅塞現象,系統即會開始執行
QoS 分級處理:
要派送給訂閱者接收的訊息,若 QoS 等級較低,會被捨棄;而 QoS 等級較高者,系統會為其找一個
QoS 等級較其低者加以取代,將其擠入待發區中。如此一來,針對每一個獨立的訊息接收者,在訊息待發區大小無法無窮擴大的情況下,讓發送者有能力決定在傳輸品質不佳下的訊息服務品質。
ActiveX API
只要是叫用發送 Subject 訊息的函式,就必須在參數中給定 qos 品質等級,如下
ipushSendPSubjectData()
所示者:
long ipushSendPSubjectData(BSTR
subject, VARIANT* data, long priority, long qos,
long days, long hours, long minutes, long seconds)
其中的 qos 為 long 資料型態,有效範圍值為 0 ~ 3 的整數。
Java Class API
只要是叫用發送 Subject 訊息的函式,就必須在參數中給定 qos 品質等級,如下
ipushSendPSubjectData()
所示者:
public int ipushSendPSubjectData(int
index, String subject, String msg, byte priority, byte
qos, int days, int hours, int minutes, int seconds)
其中的 qos 為 byte 資料型態,有效範圍值為 0 ~ 3 的整數。
<Message Priority>
由叫用發送函式中給定的 priority
參數值來決定一個 Subject 訊息的 Message Priority 等級
Message Priority,翻成中文為 "訊息優先順序"。這個機制與上面所提到的
QoS 非常相似,也是為每一筆 Subject 訊息標示它的優先等級;Message Priority 等級越高者,iPush®
Server 將會優先處理和發送。
Message Priority 等級從 1 ~ 15,共 15 級,數字越大,優先等級越高。
讀者一定很好奇,為什麼會有兩個類似的機制存在於 iPush®
V2 中呢?它們的運作有何不同?
答案是這樣的:雖然 Message Priority 與 QoS 都被拿來定義一筆訊息的重要性,以做為
iPush® Server 優先處理的準則,但是這兩者作用的範圍不同。Message
Priority 容許訊息在待發區中插隊,而 QoS 則否。
當訂閱接收者的訊息待發區出現壅塞時,QoS
分級作業會先被執行。一旦壅塞時,iPush® Server 進行訊息排送任務,會先檢查該訊息的
QoS 等級,等級較高的訊息會被排入訊息待發區中,如上所述。之後,系統會再依該訊息被標示的 Message Priority
等級,越過待發區中 Priority 等級較低的訊息,將其排在同一 Priority 等級的最後。
綜合以上 QoS 與 Message Priority 的運作,有兩個很重要的觀念要提醒:
-
如果說訂閱接收者專屬的訊息待發區根本就收發順暢,並無壅塞的情況出現,那麼,系統根本就不會也不必啟動
QoS 與 Message Priority 分級作業。
-
在實際應用時,每一個訊息的
QoS 等級與 Priority 等級,都是由訊息發送者指定的。也就是說,訊息發送者必須根據應用的性質,先行為每一個訊息決定當接收者的訊息待發區發生擁塞狀況時,iPush®
Server 該如何處理該訊息?是要捨棄,還是將另一個訊息取代掉;要不要讓它具有插隊的權力?賦予它插隊的權力等級是多高?而
iPush® Server,只不過是聽從這些等級指示做事罷了。
ActiveX API
只要是叫用發送 Subject 訊息的函式,就必須在參數中給定 priority 品質等級,如下
ipushSendPSubjectData()
所示者:
long ipushSendPSubjectData(BSTR
subject, VARIANT* data, long priority, long qos,
long days, long hours, long minutes, long seconds)
其中的 priority 為 long 資料型態,有效範圍值為 1 ~
15 的整數。
Java Class API
只要是叫用發送 Subject 訊息的函式,就必須在參數中給定 priority 品質等級,如下
ipushSendPSubjectData()
所示者:
public int ipushSendPSubjectData(int
index, String subject, String msg, byte priority,
byte qos, int days, int hours, int minutes, int seconds)
其中的 priority 為 byte 資料型態,有效範圍值為 1 ~
15 的整數。
<Time-To-Live>
由叫用發送函式中給定的 days /
hours / minutes / seconds 參數值來決定一個 Persistent
Subject 訊息的 TTL
時間
Time-To-Live,可簡寫為 TTL,翻成中文為 "有效期限",只有
Persistent Subject 訊息才能被賦予 TTL 屬性,Non-persistent Subject
訊息是沒有這個屬性的。
在 Persistent Subject 訊息傳遞的環境中,TTL
表示了該訊息被儲存後,可以在系統內存活的最久時間 (單位為秒)。
為什麼 Persistent Subject 訊息要有
TTL 存活期限呢?
這跟我們還未詳述的另一訊息保證送達特性 ── Store-and-Forward
運作有關︰當 Persistent Subject 訊息通過
iPush® Server
時,系統會將訊息儲存起來,並等訂閱接收者送回應 (Ack) 確認後,即會將該訊息刪除。
但是,如果系統永遠都無法接到回應確認,或是接收者根本就很長一段時間未上線時,訊息不就會一直停留在系統中了嗎。有鑑於此,TTL
就是被設計用來讓系統判斷,何時可以將一個 Persistent Subject 訊息刪除,而不需痴痴等待接收者遲遲不來的回應,或是根本就不再上線接收訊息的使用者。
ActiveX API
只要是叫用發送 Persistent Subject 訊息的函式,就必須在參數中給定由
days / hours / minutes / seconds 組成的相對可存活期限 (最後計算單位為秒),如下
ipushSendPSubjectData()
所示者:
long ipushSendPSubjectData(BSTR
subject, VARIANT* data, long priority, long qos, long
days, long hours, long minutes, long
seconds)
days 為 long 資料型態。
hours 為 long 資料型態。
minutes 為 long 資料型態。
seconds 為 long 資料型態。
TTL = days X 86400 + hours X
3600 + minutes X 60 + seconds
Java Class API
只要是叫用發送 Persistent Subject 訊息的函式,就必須在參數中給定由
days / hours / minutes / seconds 組成的相對可存活期限 (最後計算單位為秒),如下
ipushSendPSubjectData()
所示者:
public int ipushSendPSubjectData(int
index, String subject, String msg, byte priority, byte
qos, int days, int hours, int minutes,
int seconds)
days 為 int 資料型態。
hours 為 int 資料型態。
minutes 為 int 資料型態。
seconds 為 int 資料型態。
TTL = days X 86400 + hours X
3600 + minutes X 60 + seconds
<Connection ID>
接收者隨 Subject 訊息接收到的 connId
參數值 (ActiveX Event) 或 CID 參數值 (Java interface) 可以得知發送者的
Connection ID
Connection ID,翻成中文為 "連線編號"。每個 Connection
ID 長度為 12-bit,其有效期只在該次連線期間,一旦使用者連線終止,下次再建立連線的 Connection
ID 即會不同。
每一個連結上 iPush® Server 的客戶端連線,不管是
TCP 還是 UDP 連線 (即叫用 ipushTCPConnect()
或 ipushUDPConnect()
成功),皆會被系統賦予一個獨一無二的 Connection ID,以供識別應用;但這個 Connection ID
只會隨 Subject 訊息被外界得知。
iPush® Server 在推播 Subject
訊息給訂閱者接收時,會將該訊息發送者的 Connection ID 隨 ActiveX Event 或 Java
interface 一併告知接收者。在應用時,可以據此建立連線期間的使用者身分安全認證系統,或是將 Connection
ID 做為後續要與發送者通訊自動化 Subject Naming 的一部份。
ActiveX API
iPush® Server 推送 Subject 訊息給訂閱者接收時,接收者的
API 會丟出 Event SetSubjectData(),其中的
connId 參數值即是訊息發送者的 Connection
ID,如下所示者:
SetSubjectData(BSTR
subject, BSTR durableName, VARIANT* data, long connId,
long msgId)
其中的 connId 為 long 資料型態。
Java Class API
iPush® Server 推送 Subject 訊息給訂閱者接收時,接收者的
API 會丟出 interface iPush2MsgListener 中的 Method
onSubjectMessage(),其中的
CID 參數值即是訊息發送者的 Connection
ID,如下所示者:
public void onSubjectMessage(int
ipushno, String subject, String durname, byte msg[], int
msglen, int CID, long MsgID)
其中的 CID 為 int 資料型態。
<Message ID>
接收者隨 Subject 訊息接收到的 msgId
參數值 (ActiveX Event) 或 MsgID 參數值 (Java interface)
可以得知該訊息的 Message ID
Message ID,翻成中文為 "訊息編號"。每個 Message
ID 長度為 32-bit,且為唯一。
每一個被傳送到 iPush® Server 的 Subject
訊息,不管是 Pub/Sub 還是 P2P 傳遞模式,皆會被系統賦予一個獨一無二的 Message ID,以供識別應用;但這個
Message ID 只會隨 Subject 訊息被外界得知。
iPush® Server 在推播 Subject
訊息給訂閱者接收時,會將該訊息的 Message ID 隨 ActiveX Event 或 Java interface
一併告知接收者。在應用時,可以直接將 Message ID 顯示出來,也可以據此建立傳送歷史,或是形成如 Newsgroup
的討論串。
ActiveX API
iPush® Server 推送 Subject 訊息給訂閱者接收時,接收者的
API 會丟出 Event SetSubjectData(),其中的
msgId 參數值即是該訊息的 Message ID,如下所示者:
SetSubjectData(BSTR
subject, BSTR durableName, VARIANT* data, long connId,
long msgId)
其中的 msgId 為 long 資料型態。
Java Class API
iPush® Server 推送 Subject 訊息給訂閱者接收時,接收者的
API 會丟出 interface iPush2MsgListener 中的 Method
onSubjectMessage(),其中的
MsgID 參數值即是該訊息的 Message ID,如下所示者:
public void onSubjectMessage(int
ipushno, String subject, String durname, byte msg[], int
msglen, int CID, long MsgID)
其中的 MsgID 為 long 資料型態。
截至目前為止 (2004.02.10) 我們在 ICE
Developer Center - Download 區中提供下載的 iPush®
V2 APIs,版本編號如下:
以上並未實作 QoS、Connection ID 等屬性。完全支援上述訊息屬性的
iPush® V2 APIs 將會很快於近日推出,並再增添 Linux C 版本。屆時我們會再通知
ICE Developer Center 會員,歡迎下載試用。
當然,若您已經使用現有的 iPush®
V2 APIs 開發了應用程式,屆時要使用新版的 APIs,就必須要修改一下函式呼叫的程式碼。 |