本節書摘來自華章社群《低功耗藍牙開發權威指南》一書中的第2章,第2.11節範式,作者 (英)robin heydon,更多章節内容可以通路雲栖社群“華章社群”公衆号檢視
2.11 範式
最成功的技術常圍繞不同的範式而設計,低功耗藍牙也不例外。低功耗藍牙技術使用兩個主要的架構範式:用戶端–伺服器架構和面向服務的架構。
2.11.1 用戶端–伺服器架構
在用戶端–伺服器架構中,用戶端通過網絡向伺服器發送請求,伺服器回複響應。這是網際網路背後的主要範式,無疑也是有史以來釋出的最成功的網絡技術。
舉個例子,當你在web浏覽器中鍵入一個url位址時,它首先發送位址到dns伺服器。dns伺服器将已配置設定給該名稱的對應的ip位址傳回。然後,用戶端通過超文本傳輸協定(http)向伺服器發送請求,一旦連接配接确立,請求伺服器發送所要求的資源。接着伺服器回複适當的資源,通常是一個包含了标記資訊(html)的文本檔案,告訴浏覽器如何顯示資訊。
該檔案還可以包含一些url供用戶端擷取資源,如圖檔或其他頁面。這些額外的連結被視為html頁面彼此連結成一個巨大的web網絡的真正原因,也正是因為這樣,才有了web頁面和web伺服器的說法。
關于伺服器和用戶端的分工問題,二者有明确的區分。伺服器通常以結構化形式儲存資訊,可以說,這些資訊正是伺服器存在的真正原因。資訊可以是任何形式的資料,比如目前夏威夷科納區的天氣,下一班從首爾市區到機場的火車的時刻表,或隻是一群朋友間的閑談。另一方面,用戶端沒有任何資料,隻是将請求發送到伺服器。一旦從伺服器收到答複,就可以執行指定的任務,例如為使用者顯示資訊或發送通知,告訴他們認識的某人剛在推特上發了些東西。
用戶端–伺服器架構的主要優點是将用戶端和伺服器二者劃分開來。當系統的不同部分位于不同的裝置上時,這種劃分必不可少。将其中一部分作為伺服器而另一部分作為用戶端,系統中二者的關系随之确定下來。
這種架構的主要優點是便于擴充。除了能夠通路資源的url,用戶端不需要知道任何東西。用戶端的數量也可以十分龐大,一些網際網路的網站每天可能收到來自數百萬客戶的請求。伺服器并不真正關心這些用戶端是誰或來自何處,它隻是對每一個請求做出響應。
該伺服器架構亦可進行拓展。用一台機器每天響應數百萬的請求可能導緻過載甚至服務失效。解決的辦法是使用許多相同的、有權通路相同資訊的伺服器。還有個辦法是将同一個域名解析成不同的ip位址告訴不同的用戶端,使負載均勻地分布在各伺服器之上。這就是所謂的負載均衡。
2.11.2 面向服務的架構
用戶端–伺服器架構之上的進一步抽象是面向服務的範式。這是一個将伺服器中的資訊組織成服務的模型。該服務可以被發現、進行互動或用做已知的語義。這意味着該服務具有确定的行為,在給定相同的條件時,總會産生同樣的結果。
這種範式是最成功的網際網路系統的基礎,如soap、rest、cobra、rpc、web服務等。
為了更好地說明這一點,一種方法是把它與現實世界的例子相結合。假設有一個包裹需要盡快傳遞給另一家公司,你可能會做的第一件事是打電話給快遞公司安排取件,然後支付服務費。關鍵在于,你總是知道接下來會發生什麼,快遞公司始終遵循一套預設的行為:無論哪天給他們一個包裹,他們所做的事情都完全一樣—把它及時地快遞到目的地。這項服務具有預先确定的行為和已知的語義,并産生可預測的結果。
上述例子裡有一個有趣的地方,你和快遞公司的兩個不同的人打了交道:接電話并接受業務請求的人以及上門取件的快遞司機。此外,也許你并未意識到,其實還有一個處理财務賬款的人。三人提供的子服務互相結合,形成了快遞公司的主營服務。
這些子服務也是通用的,它們可以用于許多不同類型的公司。比如财務事務處理幾乎能以同樣的方式應用到各家公司。類似地,利用電話的方式在某個地方裝貨且在另一個地方卸貨的服務也可以被應用于計程車公司。
這一切要運轉,每個環節都必須遵循一套規則和慣例,下面将對此進行詳細介紹。
正式合約
一個服務之是以被視為服務,是因為其在公開的功能以及如何工作兩個方面提供了正規的描述。例如,快遞公司的司機穿着公司制服,駕駛公司車輛,并愉快地迎接客戶。他會在不同地點之間快速、安全地駕駛車輛,将包裹完好無損地送達。任何違反這些規則的行為将被視作違反了客戶與快遞公司之間的合約。是以,大多數快遞公司也要求客戶首先同意這種正式合約,然後才去取包裹。
正式合約的一個好處在于,一個服務的執行個體很容易被另一個服務的執行個體所代替。隻要兩個服務的執行個體具有相同的功能和行為,這種情況就有可能發生。例如一個财務人員離開了公司,公司應該很容易找到一個知曉相同做賬規則的替代者。
在低功耗藍牙中,這些正式合約位于服務規範之中,并為藍牙sig所采用。這些規範也有相應的測試規範,以確定實施行為的有效性。
松耦合
在面向對象的軟體中,單獨的系統元件是指被設計成無邊界效應的獨立對象。那些發生在元件之間的互相作用可以被明确地定義和測試。
将依賴關系減少到最低限度,使修改服務的實作時不會帶來意想不到的邊界效應,進而降低風險。從這一點出發可以得到一個合理的推論,即應當将正式合約及其實作這二者分離開來。這樣,隻要正式合約不被破壞或修改,實作就可以根據需要随意變換。
打個比方,快遞公司可以增加更多的司機,把一個司機完成所有工作的局面變成很多司機在城市的一小塊區域内取件、運回分揀中心、再發送到目的地,而這些工作可能由不同的司機完成。從客戶的角度來看,該服務依然如故,包裹仍然按照預期被收走而後送達,但實作的過程卻是完全不同的。注意,這裡并未改變财務服務或訂單服務。
抽象化
服務抽象是十分重要的設計原則,如果違背該原則可能造成嚴重的後果。假如不利用抽象化,而讓用戶端掌握服務的所有實作細節,那麼用戶端使用該服務的方式将會嚴重制約服務的演化。
知識總是多多益善,這雖然是個常識,但在面向服務的體系結構下,用戶端對服務的實作知識了解得越少越好。太多的知識會讓用戶端與某種具體的實作發生關聯,進而妨礙服務的重用或是重新設計。一旦服務的實作發生變化,用戶端有可能崩潰。
為了確定遵循該原則,服務公開的狀态應當盡可能少。此外,隻應規定服務行為的外在表現。
可重用性
可重用性的概念多年來一直是面向對象方法所期望的設計目标。但是,真正意義上的可重用性是令服務适用于多種不同應用的一種能力。如果未經認真思考,設計的服務往往僅能完成某一種工作。而在良好的設計方案中,服務可以與具體的實作過程互相獨立。這意味着該服務能夠在其他應用程式中快速、輕松地獲得重用。
藍牙技術聯盟為應對這一挑戰設立了一個工作組,該工作組的唯一工作就是找尋通用的功能,對其需求進行抽象以實作有效的重用。
無狀态
為了讓衆多用戶端支援服務擴充,伺服器不能儲存任何用戶端的狀态資料。伺服器或許可以定義一個服務用來記住用戶端已經告訴它們的所有資訊,使用戶端在後續請求時不必重複這些資訊。但該方法的問題在于,這些資訊占用了大量的記憶體,且依賴于用戶端和伺服器二者之間同步的共享狀态資訊。這将導緻伺服器完全依賴用戶端的正确操作,而這樣的假設無疑站不住腳。
是以,無狀态的設計目标是删除用戶端和伺服器之間所有的互動狀态。雖然仍然有一些狀态資訊存儲在伺服器上,但是它們均為伺服器狀态,而非用戶端狀态。這意味着,無論任何用戶端在任何時間發送任何請求,伺服器都将以完全相同的方式響應相同的請求,而不管請求來自哪個用戶端。
可組合性
上面提及的各種目标意味着,服務應該被設計得小而簡單,然而現實世界從來都不是那麼簡單。現實世界中的服務是複雜的。要解決這個明顯的沖突沖突,面向服務的體系結構鼓勵聚合較小的服務,以實作更進階的服務接口。
這一設計目标鼓勵服務間互相組合。例如,快遞公司的服務是由三個獨立的服務組成的,這些單獨的服務隻要圍繞既定目标,就可以合并成一個快遞公司。同樣,一些服務可以結合在一起組成計程車公司或商務汽車租賃服務。盡管實作不盡相同—送貨車、家用車、行政豪華轎車,但本質上是相同的服務。
自治
為了重用群組合服務,服務本身必須是可靠的。基于系統内其他元件構造的服務在執行請求處理的可靠性上無疑要比對所有事情實施完全控制的服務更差。
自治的服務可以獨立執行任務,而不管在其周邊發生的情況。這些服務要在其他應用程式中實作重用将會非常容易。非自治服務可能會帶來許多額外的支撐服務,并且可能與其他服務相沖突。
例如,快遞公司的司機們按照規定自主活動,完成包裹收集和遞送。即使辦公室那邊出了岔子,他們仍能繼續獨立地工作。
可發現性
最後,要想使用服務就必須能夠發現服務。乍看上去似乎顯而易見,但其實服務發現能力在移動自組織網絡中是必不可少的。沒有服務發現,所有服務必須采用靜态程式設計,複雜、繁瑣而且容易出錯。
可發現性通常是通過一個單獨的、與服務互動的協定來實作的。比方說,要找到快遞公司,人們應當使用電話簿或在網際網路上搜尋,絕不會是随機撥打電話号碼并希望接通的是個快遞公司。
低功耗藍牙采用不同的方法:使用同一個協定實作服務發現以及服務互動。該協定稱為“屬性協定”,服務可發現性在其規範中被稱為“通用屬性規範”。這二者都将在第10章中進行介紹。