編輯:關於Android編程
前段時間我們翻譯的《軟件架構模式》( 完整書籍的地址 ) 對外發布之後得到了大家的一致好評,書中講述了五種經典、流行的軟件架構模式,同時分析了五種模式的實現、優缺點等,為我們的開發工作提供了很有價值的指導。但是《軟件架構模式》的問題在於沒有結合具體的示例來讓這些理論知識更易於吸收,因此有些同學在我的開發群反饋: 書看起來是挺好的,但是沒有具體的示例感覺看得迷迷糊糊的。因此在下打算寫一些結合Android源碼或者開發的文章來更深入的講述這些架構模式,理論與實踐相結合,讓大家更深刻、更具體的學習到這些架構的魅力所在。
由於微服務架構模式的高度靈活性、伸縮性等因特性,近年來在業內發展迅猛。但由於這個架構模式仍然在不斷的發展中,業內人士對這個模式也存在很多困惑,例如這個模式是關於什麼的?它是如何實現的?本文首先為講述這個模式的關鍵概念、基礎知識以及這個架構模式的優缺點,因為只有在對它有深入的了解之後你才能根據實際情況來判斷你的應用是否適合這種架構。
不管你選擇哪種實現,有幾個常見的核心概念都需要進行了解。第一個概念是獨立部署單元。如圖4-1所示,微服務架構的每個組件都作為一個獨立單元進行部署,讓每個單元可以通過有效、簡化的傳輸管道進行通信,同時它還有很強的擴展性,應用和組件之間高度解耦,使得部署更為簡單。
也許要理解這種模式,最重要的概念就是服務組件。不要考慮微服務架構內部的服務,最好是考慮服務組件,從粒度上講它可以小到單一的模塊,或者大至一個應用程序。服務組件包含一個或多個模塊(如Java類),這些模塊可以提供一個單一功能,例如為特定的城市或城鎮提供天氣情況,或也可以作為一個大型商業應用的一個獨立部分,例如火車票的余票查詢系統。在微服務架構中,正確設計服務組件的粒度也是一個很大的挑戰。在接下來的服務組件部分對這一挑戰進行了詳細的討論。
微服務架構模式的另一個關鍵概念是它可能是一個分布式的架構,這意味著架構內部的所有組件之間是完全解耦的,並通過某種遠程訪問協議(例如, JMS, AMQP, REST, SOAP, RMI等)進行訪問。這種架構的分布式特性是它實現一些優越的可擴展性和部署特性的關鍵所在。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPs6it/7O8bzcubnB7dK7uPbB7sjL0Mu33LXEzNjQ1MrHy/zKx9PJxuTL+7OjvPu83Lm5xKPKvbTm1Nq1xM7KzOLR3buvwLS1xKOstviyu8rH1/fOqtK7uPa94r72t72wuLG7tLTU7LP2wLS1yLT9zsrM4rP2z9aho86it/7O8bzcubm1xNHdu6/T0MG9uPbW99KqwLTUtKO6yrnTw7fWsuO83Lm5xKPKvbXEtaXM5dOm08O6zcq508PD5s/yt/7O8bzcubm1xLfWsrzKvdOm08OhozwvcD4NCjxibG9ja3F1b3RlPg0KCTxwPszhyr4gOiC1pczl06bTwywgvLTSu7j206bTw77NysfSu7j21fvM5aGjPC9wPg0KPC9ibG9ja3F1b3RlPg0KPHA+tNO1pczl06bTw7W9zqK3/s7xtcS3otW5uf2zzNb30qrKx9PJs9bQ+L27uLa/qreitNmzybXEoaO1pczl06bTw82os6PKx9PJvfTx7rrPtcTX6bz+1+mzyaOs1eLQqdfpvP7NrMqx09bKx8Ht0ru49rWl0ru/ybK/yvC1pdSqtcTSu7K/t9ajrNXiyrm1w8v8t7HL9qOsxNHS1LjEseShorLiytS6zbK/yvDTptPDoaPV4tCp0vLL2M2os6O74bW81sLTptPDseS1w7TgyPWjrNLU1sHT2sO/tM7T0NK7tePQwrmmxNyyv8rwuvOjrMjnufvTydPa1eLQqdDCuabE3NL9t6LBy9Lss6OjrMTHw7TV+7j206bTw77NsrvE3NTL0NCho86it/7O8bzcubnEo8q9zai5/b2r06bTw7fWuPSzybbguPa/ybK/yvC1xLWl1KqjqLf+zvHX6bz+o6m1xLe9t6jAtL3ivvbV4tK7zsrM4qOs1eLQqbf+zvHX6bz+v8nS1LbAwaLT2sbky/u3/s7x1+m8/r340NC1pbbAv6q3oqGisuLK1LrNsr/K8KGjPC9wPg0KPHA+we3Su7j2tbzWws6it/7O8bzcubnEo8q9svrJ+rXE0d27r7n9s8zKx9PJw+bP8rf+zvG83Lm5xKPKvaOoU09Bo6nTptPDs8zQ8rTm1Nq1xM7KzOLS/cbwtcSho8vkyLtTT0HEo8q9t8ezo8e/tPOjrMzhuanBy87e0+vC17HItcSz6c/zvLax8KGi0uy5ucGsvdOhorf+zvG197bIo6yyorGj1qTNqLn9SVTE3MGmtffV+9K1zvHEv7Hqo6y1q8v8yNTIu8rHuLTU07XEoaKwurnztcQsy/y63MTRwO294rrNyrXP1qOsttS087bgyv3TptPDs8zQ8sC0y7XL/Ln909rW2MG/vLaho86it/7O8bzcubnNqLn9vPK7r7f+zvG4xcTuo6zP+7P9tfe2yNDox/Ohorzyu6+3/s7x1+m8/sGsvdO6zbfDzsrAtL3ivva4tNTTtsjOyszioaM8L3A+DQo8cD4mbmJzcDs8L3A+DQo8aDMgaWQ9"12-模式拓撲">1.2 模式拓撲
雖然有很多方法來實現微服務架構模式,但三個主要的拓撲結構脫穎而出,最常見和流行的有:基於REST API的拓撲結構,基於REST的應用拓撲結構和集中式消息拓撲結構。
基於REST的API拓撲
圖 4-2
圖 4-3
圖 4-4
微服務架構模式的主要挑戰之一就是決定服務組件的粒度級別。如果服務組件粒度過粗,那你可能不會意識到這個架構模式帶來的好處(部署、可擴展性、可測試性和松耦合)。然而,服務組件粒度過細將導致額外的服務調度,這可能會導致將微服務架構模式變成一個復雜、容易混淆、代價昂貴並易於出錯的、重量級的面向服務架構。
如果你發現需要從應用內部的用戶接口或API層調度服務組件,那麼很有可能你服務組件的粒度太細了。同樣的,如果你發現你需要在服務組件之間執行服務間通信來處理單個請求,要麼是你服務組件的粒度太細了,要麼是沒有從業務功能角度正確劃分服務組件。
服務間通信,可能導致組件之間產生耦合,但可以通過共享數據庫進行處理。例如,若一個服務組件處理網絡訂單而需要用戶信息時,它可以去數據庫檢索必要的數據,而不是調用客戶服務組件的功能。
共享數據庫可以處理信息需求,但是共享功能呢?如果一個服務組件需要的功能包含在另一個服務組件內,或是一個公共的功能,那麼有時你可以將服務組件的共享功能復制一份,因此違反了DRY規則。為了保持服務組件獨立和部署分離,微服務架構模式實現中會存在一小部分由重復的業務邏輯而造成的冗余,這在大多數業務應用程序中是一個相當常見的問題。小工具類可能屬於這一類重復的代碼。
提示 : DRY,即don’t repeat yourself.
如果你發現就算不考慮服務組件粒度的級別,你仍不能避免服務組件調度,這是一個好跡象,可能此架構模式不適用於你的應用。由於這種模式的分布式特性,很難維護服務組件之間的單一工作事務單元。這種做法需要某種事務補償框架回滾事務,這對此相對簡單而優雅的架構模式來說,顯著增加了復雜性。
微服務架構模式解決了很多單體應用和面向服務架構應用存在的問題。由於主要應用組件被分成更小的、單獨部署單元,使用微服務架構模式構建的應用程序通常更健壯,並提供更好的可擴展性,支持持續交付也更容易。
該模式的另一個優點是,它提供了實時生產部署能力,從而大大減少了傳統的月度或周末“大爆炸”生產部署的需求。因為變化通常被隔離成特定的服務組件,只有變化的服務組件才需要部署。如果你的服務組件只有一個實例,你可以在用戶界面程序編寫專門的代碼用於檢測一個活躍的熱部署,一旦檢測到就將用戶重定向到一個錯誤頁面或等待頁面。你也可以在實時部署期間,將服務組件的多個實例進行交換,允許應用程序在部署期間保持持續可用性(分層架構模式很難做到這點)。
最後一個要重視的考慮是,由於微服務架構模式可能是分布式的架構,他與事件驅動架構模式具有一些共同的復雜的問題,包括約定的創建、維護,和管理、遠程系統的可用性、遠程訪問身份驗證和授權等。
下面這個表中包含了微服務架構模式的特點分析和評級,每個特性的評級是基於其自身特點,基於典型模式實現的能力特性,以及該模式是以什麼聞名的。
在Android領域中,我們最常看到的就是如圖4-5的Android體系架構。
圖4-5
這是一個典型的分層架構,分為應用層、Framework層、Native層、內核層。這似乎與我們今天要說的微服務架構沒有任何關系!大家需要注意的是這是一個更為宏觀的架構,在這個分層架構之下還有其他的架構模式,微服務架構就是其中最為明顯的一個。Android系統按照職責分為不同的層次,但是在Java層( Java應用程序和應用程序框架)與系統服務層( Android運行環境 )這兩個層之間則是通過本地C/S模式進行通信,也就是我們的微服務架構。
我們知道在Android系統啟動時,大致會執行如下四步:
init進程啟動;; System Server啟動; Android系統服務啟動,將服務注冊到ServiceManager中; Android運行環境建立,並且啟動Launcher程序。在init進程啟動後,會調用init_parse_config_file方法解析init.rc文件,然後將init.rc中指定的命令、服務等啟動起來。
int main(int argc, char **argv)
{
// 代碼省略
// 創建系統文件夾
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
// 代碼省略
// 初始化內核
open_devnull_stdio();
klog_init();
property_init();
process_kernel_cmdline();
// 代碼省略
// 解析init.rc文件
init_parse_config_file("/init.rc");
// 代碼省略
return 0;
}
init.rc是由一種被稱為“Android初始化語言”的腳本寫成的文件。在該文件中描述了一些動作、命令、服務、選項等,我們這裡只關心服務這一項。init.rc中的一個服務描述大致是這樣的。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
在上述代碼中指定了一個zygote服務,這個服務會啟動一個叫做zygote的進程,zygote是Android世界的萬物之源,所以的進程都有它孵化。在啟動zygote時又會啟動System Server進程,System Server是所有系統服務的棲息地,也是應用與Zygote進程通信的中樞,例如需要啟動某個應用時會通過System Server通知zygote fork一個新的進程。在System Server啟動之後會調用com_ android_ server_ SystemServer. cpp類中的android_server_SystemServer_nativeInit函數,在該函數中會獲取ServiceManager實例以及啟動一些Native服務。最後會調用SystemServer內部類ServerThread的initAndLoop函數將WindowManagerService、ActivityManagerService等系統服務注冊到ServiceManager中,這些服務為系統提供各種各樣的功能,最後啟動系統消息循環,此時Android的運行環境基本構建起來了。
public class SystemServer {
// 主函數
public static void main(String[] args) {
// 代碼省略
// Initialize native services.
nativeInit();
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
}
// 內部類
class ServerThread {
public void initAndLoop() {
// 1、啟動主線程消息循環
Looper.prepareMainLooper();
// 代碼省略
try {
// 2、將各個系統服務注冊到ServiceManager中
// 添加PackageManagerService
pm = PackageManagerService.main(context, installer,
wm = WindowManagerService.main(context, power, display, inputManager,
wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
// 添加 WindowManagerService
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
// 數十種服務的注冊,代碼省略
} catch (RuntimeException e) {
}
// 3、啟動消息循環
Looper.loop();
}
} // end of ServiceThread
} // end of SystemServer
Framework層(客戶端)與Native系統服務(服務端)之間並不是直接調用的,而是通過Binder機制,客戶端代碼通過Java端的服務代理與Bidner機制向Native服務發起請求,具體的工作交給Native系統服務來實現。因此Framework和Native層的架構是如圖 4-6 所示。
這種架構就是類似上文所說的基於API的微服務架構,Native層系統服務完成具體的功能,Java層提供訪問Native系統服務的接口,它們之間通過Binder機制進行通信,Java層與Native層就是一個本地的C/S架構。如果以一個有網絡請求的App做比喻的話,App客戶端就扮演了Java層的角色,Native層系統服務對應的是服務端,而通信機制則由http變成了Binder。Native層的系統服務多達數十種,每個系統服務的職責明確、單一,具有良好的內聚性。例如WindowManagerService只負責管理屏幕窗口相關的操作。通過這種微服務架構,使得Java層與Native層耦合性很低、伸縮性很高,也對Java層隱藏了復雜的實現,使得整個系統更為清晰、靈活。
微服務架構以其優秀的靈活性、伸縮性在各個架構模式中脫穎而出,但是它的一個弱點是性能相對較低。因為客戶端與服務提供端需要進行IPC甚至是網絡請求,這就通信成本較高。在Android中客戶端和服務端都在本地,因此需要IPC機制。Android並沒有選擇像Socket、管道等傳統的IPC機制,而是選擇了更為靈活、簡潔和快速、低內存消耗的Binder,這也在很大程度上提升了微服務架構在Android系統中性能以及開銷。因此,如果在普通應用中運用這種架構時,首先需要考慮的就是性能的開銷,靈活度、內存帶來的益處是否大於性能降低帶來的弊端,這些就需要大家以自身情況而定了。
剛入門的童鞋肯能都會有一個疑問,Java不是有虛擬機了麼,內存會自動化管理,我們就不必要手動的釋放資源了,反正系統會給我們完成。其實Java中沒有指針的概念,但是指針的使
Volley是Android系統下的一個網絡通信庫,為Android提供簡單快速的網絡操作(Volley:Esay, Fast Networking for Androi
前陣子要的工作是給桌面(Launcher啟動器,其實也是一個activity)添加一個觸摸特效(一個View),而這個特效是每次觸碰都會有,不管你在桌面上做什麼操作都會顯
首先新建一個binding Library項目,項目名隨意,我這裡起名Bmap 然後將jar文件放入jars目錄下,生成屬性改為EmbeddedJar這時候如果