1. 程式人生 > >SLP 系列第 1 部分:基本介紹和對比分析

SLP 系列第 1 部分:基本介紹和對比分析

SLP(Service Location Protocol, 服務位置協議)是一個基於 internet 標準的 RFC 規範,主要用於在網路上服務的動態發現。本文簡要介紹了 SLP 的基本內容,把它和現在其它主要的類似協議(uddi, ssdp)進行比較,分析其優缺點和應用場景。然後,本文通過一個開源包 OpenSLP 展示該協議在程式設計時的用法。

SLP 基本介紹

SLP 是一個 IETF 標準協議,用於在網際網路內動態的服務發現。該協議支援通過服務的型別,屬性來在網路中查尋服務。同時,服務的提供者可以在網路中廣播自己或者向集中式服務目錄註冊自己所提供的服務。

SLP 的結構與運作方式

在 SLP 中有三種角色:UA(User Agent, 使用者代理 ),SA(Service Agent, 服務代理 ),DA(Directory Agent, 目錄代理 )。UA 是 SLP 中的客戶端,它可以根據服務的型別和屬性,在網路中查詢符合條件的服務。SA 是 SLP 中的伺服器端,它提供了它所代理的服務的基本資訊,並與 UA 與 DA 互動。DA 是一個可選的角色,它提供了一種集中式目錄服務,SA 可以在上面註冊服務,並由 UA 來查詢,這樣 UA 與 SA 可以不必直接通訊,在大型網路中可以有效降低網路流量。SLP 結構如圖 1 所示。

圖 1:SLP 架構示意圖
圖 1:SLP 架構示意圖

DA 的存在與否可以把 SLP 的運作分為兩種模式。當網路中沒有 DA 時,UA 直接向整個網路傳送多播或廣播的查詢請求,網路中的 SA 收到請求之後,根據查詢條件判斷自己是否符合要求,如果不符合則簡單的不予迴應,否則單播 UA 說明自己符合該查詢要求,並把服務的訪問地址告訴 UA,這樣 UA 端的應用系統就可以使用該服務了。該模式運作如圖 2 所示。

圖 2 無 DA 時 SLP 運作模式示意圖
圖 2 無 DA 時 SLP 運作模式示意圖

當 DA 存在時,SA 單播 DA,在上面註冊自己的資訊,註冊內容包括服務的地址,型別和屬性。當註冊成功後,DA 回覆一條資訊確認。如果服務發生變化,SA 需要通知 DA 修改自己的註冊資訊,或者取消註冊。而當 UA 查詢服務時,它不用再廣播整個網路,而是直接單播 DA,把查詢要求告訴 DA,DA 根據要求對在自身註冊的 SA 進行匹配,並把匹配的結果回覆給 UA,如果匹配成功,DA 把訪問的服務地址也告知 UA,使客戶端應用系統可以使用服務。當 DA 存在時,SLP 運作模式如圖 3 所示。

圖 3:有 DA 時 SLP 運作模式示意圖
圖 3:有 DA 時 SLP 運作模式示意圖

SLP 的應用

正是由於 SLP 擁有強大的動態服務發現功能,它在網路中有著廣泛的應用。它可以自動對網路中計算機進行配置。比如給計算機配置印表機,某臺計算機需要彩色印表機,運行於該計算機之上的 UA 只需查詢型別是印表機且屬性中包含彩色的服務即可,它就能得到網路中可用的彩色印表機並自動配置,整個過程不需要人工干預,可以給網路管理帶來極大的便利性。

除了查詢服務,我們利用 SLP 還可以得到服務的各種屬性,通過這點可以對 SLP 的應用場景進一步擴充套件,比如一臺伺服器可以作為一個服務,它當前的執行狀態和各種引數可以作為服務的屬性。可以在客戶端得到這些資料,對伺服器的狀態進行監控,甚至可以通過負載等屬性對整個伺服器群進行負載平衡的管理。對於 SLP 的進一步詳細介紹,可以查閱文後參考資料的相關內容。

SLP 與其它類似協議比較與優劣分析

在服務的發現與註冊領域,並不只有 SLP 一項技術,SLP 也不是全能的,在某些場合下,它的發揮將受到限制,使用它未必是最佳的解決方案。下面,本文把它與類似功能的兩大協議 UDDI 和 SSDP 做一對比,分析其優勢劣勢與合適的應用場景,並給出作者自己的使用建議。

SLP vs UDDI

談到服務的發現與註冊,最鼎鼎大名的可能就是 web service 的 UDDI(Universal Description, Discovery, and Integration, 統一描述,發現與整合 ) 了。在當今 SOA 的浪潮中,web service 憑藉其鬆耦合,異構通訊,自包含語義等優勢成為業界最主要的標準。而 UDDI 則提供了一個平臺供服務提供者釋出自己的服務,以及服務消費者來查詢自己需要的服務。因此,從用途上來說,UDDI 與 SLP 基本上是一致的。

兩者最大的區別還是在適用範圍上。UDDI 面對的是全球整個 internet,而 SLP 基本上都是在區域網內部使用的。造成這個區別的原因很大程度上是因為 UDDI 是基於 xml 技術,而 xml 這門語言的強大之處在於它是語義自包含的,因此在對服務的語義描述上有著先天的優勢。另外,UDDI 是作為 web service 三角架構(服務提供者,服務呼叫者,服務目錄,對應於 SLP 中的 SA,UA,DA)協議的一部分,和 wsdl 及 soap 協議協同工作的。SLP 則不得不孤軍奮戰,它既不能像 wsdl 那樣去描述一個服務,又不能像 soap 那樣去定義服務的呼叫,所有這些都是定義在 SLP 之外,又必須在使用前三方都協商好的。因此,這個大大限制了 SLP 的適用範圍,把其用武之地框定於區域網之內。畢竟在廣域網中,語義協商的代價往往是巨大的,其管理也是非常困難的。

即便在區域網內,SLP 也並非沒有挑戰。SLP 的一大特點是異構平臺的通訊,(在同構平臺中,我們經常能發現一些更適用的平臺專屬策略),但遺憾的是,這恰恰又是 web service 的長處。不過在語義問題並不佔主要因素的區域網環境中,其巨大而笨重的架構劣勢就顯露了出來。UDDI 分為白頁,黃頁和綠頁,其包含的資訊很豐富,但要維護這些資訊的工作量也很大。不少服務提供者經常懶得去維護那些註冊資訊,也使得 UDDI 上漸漸充斥著越來越多的垃圾資訊,最終大家都不願去用它而廢棄。這個缺點甚至在全球網際網路的環境中都難以被接受,比如微軟,IBM 等大型企業 5 年前建立的 UDDI 註冊中心,現在已漸漸無人問津。另外,xml 解析的開銷在現階段也是比較大的,在網路傳輸延時可以忽略的區域網中,處理 xml 的時間開銷會成為效率瓶頸。因此,在區域網中,使用者往往偏向更輕量級的解決方案,SLP 輕盈的身姿將導致使用者的青睞。使用 SLP 你不用擔心建立和維護龐大的註冊中心(即使使用 DA,其有效註冊資訊時間最長也只有 18.2 個小時,如果沒有得到 SA 的通知,DA 就會把註冊資訊丟棄),不必只為了傳輸少量資料就用大量的 xml 去包裝它們,同時又有著跨平臺的優點,是更為理想的選擇。

SLP vs SSDP

如果說 SLP 與 UDDI 由於側重應用範圍不同而沒有直接競爭的話,來自於 SSDP 的競爭威脅是更為直接的。SSDP(Simple Service Discovery Protocol, 簡單服務發現協議 ) 同樣也是一個在區域網內服務動態發現的協議,連名字都和 SLP 接近。正如其名,SSDP 非常簡單,它只定義了服務呼叫者和服務提供者兩個角色,沒有集中目錄服務,類似於沒有 DA 的 SLP。而且,SSDP 中的服務只有 4 項資料,唯一服務名,服務型別,生存週期和服務地址,並沒有詳細的服務屬性。也就是說,客戶端只能通過服務型別去查詢服務,這無疑使得查詢的靈活性和便利性大打折扣。

表面上來看,SLP 似乎完勝 SSDP,但是,SSDP 同樣不是孤軍奮戰,它是 UPnP(Universal Plug and Play, 通用即插即用 ) 協議框架中的一部分。在框架中與 SSDP 協同工作的還有用於服務描述的 UPnP 模版(可以類比 wsdl)和用於服務呼叫的 soap 協議(沒錯,還是 soap)。另外,UPnP 中還有一個通用事件通知結構 GENA,客戶端可以在服務端進行註冊,當服務端的狀態發生變化時,它會主動通知所有在自己這裡註冊的客戶端變化情況,從而使客戶端可以始終保持服務端的最新資訊,從根本上消除了過時資訊給客戶端帶來的不便。這點無論是 SLP 還是 UDDI 都不具備的。

SLP 再一次因為面對整個協議框架而受到挑戰,不過 SSDP 自身仍然有值得注意的閃光點,再看 SSDP 的四項資料,其中三項在 SLP 中都有,不過唯一服務名確是 SLP 中不具備的。這裡有一個可以討論的話題,我們是不是需要唯一辨識某一個服務,也許在 SLP 適用的大部分場合,我們不需要這麼一個辨識符,但是在有些場合下,有這麼一個辨識符可以使應用更加方便。還有一點,SSDP 是基於 HTTP 傳輸的,它可以利用很多現成的底層架構的功能,而 HTTP 在網路上的地位和通用性是無可爭議的。SLP 完全是自己定義的傳輸格式,開發的代價會比較大些。最後,UPnP 的背後有微軟的大力推動,而 SLP 似乎缺少這方面的支援,畢竟,對於標準和協議的競爭,其背後的大型企業的支援作用是巨大的。

對於這兩者的使用建議是,如果你的應用只是側重於服務的發現,那就用 SLP 吧,畢竟它比 SSDP 強大的多。但如果你想要建立一個完整的服務釋出和呼叫體系,UPnP 也許更為合適。SSDP 雖然現階段還比較簡單,但是有著 UPnP 框架的支援和微軟的推動,其發展潛力不容小覷。

SLP 應用例項與開源包 OpenSLP 介紹

下面我們來舉一個具體的例子說明 SLP 的使用方法,假如我們要編寫一個程式,其中需要使用某個印表機進行列印操作。但是我們並不知道印表機的具體配置情況,比如服務地址,這時我們就能使用 SLP 來自動發現這些印表機的資訊,把它們的地址返回給應用程式。我們還可以指定符合條件的印表機,比如在 4 樓的印表機來為我們服務。

當我們想使用 SLP 時,不必自己開發,已有不少開源專案實現了 SLP 協議,而 OpenSLP 可能是其中最著名的一個。OpenSLP 有 C 和 Java 兩個版本,C 版本相對比較成熟,已經有不少文章對其進行了介紹,我這裡就不多說了。下面我簡單介紹一下其 Java 版本的使用方法。

在 SLP 中,UA,SA,DA 的實現是相互獨立的,它們都遵照規範進行通訊,因此我們並不要求三者使用同一種實現,也不用在同種語言,同種平臺實現。遺憾的是 OpenSLP 的 Java 版本中目前還沒有 DA 的實現,SA 中也不支援向 DA 修改已註冊屬性方面的功能,但 UA 還是做的比較全的。如果你的應用系統是 Java 的,你完全可以只使用 OpenSLP 的 Java 版本的 UA 端程式包,它完全不妨礙你與網路中其它版本(比如 OpenSLP 的 C 版本)實現的 SA,DA 通訊。OpenSLP 的 C 版本實現示例可以參考我列出的《使用 Service Location Protocol 自動化客戶機的管理》一文,也可以訪問 OpenSLP 的官方網站 http://www.openslp.org 尋求幫助。

SLP 不但由 RFC2608 定義了其內容,RFC2614 還對其實現中的資料結構,呼叫介面等做了規範定義。OpenSLP 的 Java 也是完全符合該 RFC 的,程式碼中一些屬性語義,預設值和常量定義都可以參照該規範瞭解。

在使用 SLP 時,首先要對其配置屬性初始化。有三種方法初始化配置屬性,一是使用配置檔案:

File f = new File(“prop.txt”);
ServiceLocationManager.init(f);

或者使用 JavaProperties 類來初始化:

Properties p = new Properties();
p.put("net.slp.traceDATraffic", "true");
p.put("net.slp.traceMsg", "true");
ServiceLocationManager.init(p);

也可以使用預設的配置:

ServiceLocationManager.init();

如果某項屬性在前兩種方法中沒有被定義,則按照預設值來配置。

第二步我們需要得到 Locator,通過它才能進行服務發現。其中 getLocator 的引數是一個 Java 的 Locale 物件,定義了我們希望得到的服務的語言。

Locator loc = ServiceLocationManager.getLocator(java.util.Locale.US);

有了 Locator 之後我們就可以進行查詢了,查詢服務要提供以下三個引數:服務型別,範圍和查詢條件。範圍是指我們為了便於管理,人為的把網路分為幾個不同的域,可以在幾個不同的域中查詢服務。下面我們要在預設的域中查詢在 4 樓的印表機。注意這裡 location = 4F 表示 4 樓,service:printer 表示印表機,這些語義要事先在 SLP 協議之外約定。

Vector scopes = new Vector();
scopes.add("default");
String selector = "(location = 4F)";
ServiceType type = new ServiceType("service:printer");
	ServiceLocationEnumeration enumVar =
	 loc.findServices(type, scopes, selector);

在查詢之時,UA 會先試圖在網路中多播訊息尋找 DA,如果找到則向 DA 傳送查詢請求,如果超時沒有收到 DA 回覆則說明當前網路中沒有 DA 的存在,UA 再直接多播該查詢尋找 SA。當查詢請求發出以後,程式會立即返回,不用阻塞以等待 SA/DA 的回覆訊息。方法返回的 enumVar 是一個迭代器,通過它可以得到查詢的結果。

ServiceURL sUrl = null;
while(enumVar.hasMoreElements()) {
	 sUrl = (com.solers.slp.ServiceURL)enumVar.next();
 if(sUrl != null) {
 System.out.println("Found URL: " + sUrl.toString());
	 }
}

如程式碼所示,像使用普通迭代器一樣,先判斷容器中是否還有元素,如果有的話就把它取出。這裡要注意一點,在執行 hasMoreElements() 時,程式才會去接收 DA/SA 的回覆訊息,這時有可能會產生阻塞。查詢服務得到的結果是 ServiceURL 物件,其中包含服務地址 url 和生存期,這樣我們就找到那些在 4 樓的印表機的服務地址了。在這個示例中,只是簡單的把找到的所有這些 url 打印出來,在實際應用中你可以自由處理這些得到的資訊,比如給某個列印的程式配置印表機位置資訊。

總結

本文介紹了 SLP 的概念和應用,並把它與一些其他服務發現的協議比較,可以看到,SLP 在該領域功能十分強大,但是它在某些場合也有著一些不足之處。本系列專題的第二篇將討論協議的擴充套件與改進,在與當前協議相容的情況下,擴充套件協議進一步豐富其功能。

免責宣告:

1, 本文所提出的方式方法僅代表作者個人觀點。

2, 本文屬於原創作品,資料來源不超出參考文獻所列範疇,其中任何部分都不會侵犯任何第三方的智慧財產權。