国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

實例解析:設計一個完全可擴展的應用

2019-11-18 12:20:32
字體:
來源:轉載
供稿:網友

  一個軟件工程師在設計一個新的應用時有許多方面需要考慮,包括功能、性能、安全性和圖形化的用戶界面(GUI)。但是因為開始時有多種未知的和不可猜測的變數導致了一些對你來說很難發現或集成到初始設計中的隱蔽因素,就像未來將會使用你的應用的用戶數和他們的具體需求這樣的因素。由于這樣或那樣的原因,你也許在將來的某個時候需要超出它最初的設計來擴充它的功能,換句話說,擴展它。舉例來說,應用可能會處理超過它設計的更大的負載,這將會強迫你將你的應用拆分為部署在不同計算機上的更小的應用。
  
  這篇文章提供了創建這種應用的指導方針:為將來某個時候擴展應用做好預備。這些憑借經驗的規則將會使你的應用先從小規模開始,然后再根據需要來擴展它。另外,這篇文章將會介紹一組由MantaRay提供的新工具,它是一個基于點對點,無服務器架構的,革新的,開源的數據消息項目。
  
  作為例子,我們將會用到一個簡單的應用叫WebMonitor(網頁監聽器)。它最初是一個非常簡單的使用Swing編寫的GUI。應用從用戶那里得到一個URL作為輸入,并檢查該URL是否對HTTP請求有響應。應用將會不時地監聽該URL,并提供它的最新的狀態報告。
  
  圖1顯示了WebMonitor范例的GUI界面。
  
 實例解析:設計一個完全可擴展的應用(圖一)
  圖1.Webmonitor范例應用的GUI

  
  模塊化
  
  第一條規則是將你的應用拆分為模塊:代碼塊作為獨立的實體顯示,每一個實體都有它自己明確的責任。一個模塊可以由一個或多個對象構成,但反過來不行—一個對象封裝多個模塊是一種不佳實踐(在“解藕模塊”部分,我們將會說明原因)
  
  很輕易看出在WebMonitor應用中至少有兩個模塊。首先,一個GUI模塊負責取得用戶輸入和顯示結果。其次,一個引擎模塊負責檢查URL,并提供一個返回結果表明這個URL是否響應。
  
  圖2顯示了WebMonitor中的模塊
  
 實例解析:設計一個完全可擴展的應用(圖二)
  圖2.WebMonitor中的模塊

  
  實際上,有人可以指出第三個模塊,一個“模型”模塊,它就象一個數據存儲設備;當數據改變時,它通知“監聽者”模塊,這樣就完整地構成了MVC結構。這個范例的其余部分已經通過忽略第三模塊而有意簡化了,我們只集中注重力在引擎和GUI模塊上。
  
  在你的應用中把模塊標識出來是必須的,假如你還想在將來擴展你的應用的話。當時機來到的時候,模塊可以被擴展并被分解為更小的應用;這篇文章的后面我們會講到如何分解它們。
  
  解藕模塊
  
  回到我們的例子,讓我們想象一下過了一段時間,WebMonitor已經很成功了。你的客戶非常興奮,但又要求你創建其它的用戶接口。IT部想要一個命令行的用戶接口,支持部想要一個基于web的用戶接口,而開發者則想要保持Swing GUI。要想全部完成上述需求,你需要解藕WebMonitor的模塊。
  
  為了解藕模塊,我們必須確認每一個模塊是一個獨立的實體。每一個完成解藕的模塊必須是一個“黑盒子”,它有著一個明確定義的接口來和其它模塊進行通信。
  
  我們看一下WebMonitor并把它拆成若干個解藕的模塊
  
  圖3顯示了WebMonitor的解藕模塊
  
 實例解析:設計一個完全可擴展的應用(圖三)
  圖3 WebMonitor中的解藕模塊

  
  模塊間通過一個中間模塊來相互通信,這樣就將模塊解藕并消除了一個模塊所擁有的其它模塊的信息。你可以把這些中間層當成模塊間的緩沖區。雖然在這一階段這些中間層看起來并不重要,但是在這篇文章的下一節它們就變得至關重要了。
  
  當我們完成解藕以后,按客戶的要求來增加用戶界面就變得輕易了。必須的模塊加入到WebMonitor中,并在需要時與舊模塊進行通信。
  
  圖4是增加模塊以后的WebMonitor
  
 實例解析:設計一個完全可擴展的應用(圖四)
  圖4 增加完模塊以后的WebMonitor

  
  擴展應用
  
  WebMonitor應用到目前為止很成功;它監聽幾千個站點并為幾百個用戶服務。然后你開始得到報告說應用的響應正在變慢,看起來似乎引擎占用了太多的內存并且CPU已達到了機器的極限,客戶想要增加監聽的URL,但是不行,因為機器崩潰了。
  
  你所為應用所做工作―標識出了模塊并用中間層將它們解藕―馬上就可以得到回報了。既然你已把WebMonitor設計為從頭開始擴展,那么現在可以很簡單的將引擎放在不同的機器上,甚至可以創建多個引擎并在其上分配負載。因為模塊已被中間層解藕,你不需要在模塊內部重寫代碼,但對應的,你只需簡單的使用不同的中間層。這樣做,你可以無縫地將你的分布式的應用擴展到很多計算機且可以輕松地應對沉重的負載。
  
  圖5顯示了WebMonitor分布在了幾個機器上
  
 實例解析:設計一個完全可擴展的應用(圖五)
  圖5 WebMonitor分布在了幾個機器上

  
  你可能已經注重到了,中間層并沒有放在任何機器上,因為它們是可以從任何機器上引用的邏輯實體。
  
  下一節將介紹由MantaRav開源項目組提供的一組中間層,它們可以在內存中或是在一個擴展的分布式環境下工作。使用這些中間層,擴展應用不需要改變任何代碼。
  
  擴展的Stage模式和Dispatcher模式
  
  MantaRay提供了兩種中間層,點到點(stage模式)和發布-訂閱(dispatcher模式),它們針對不同的中間層需求。合在一起,它們組成一個完整的集合,可以滿足這篇文章中所有中間層需求。
  
  Stage
  
  SEDA項目定義了一個stage式事件驅動架構,引入了用于模塊交互的一個解藕良好的模型,其中,stage被用來作為模塊間的中間層。模塊將事件排隊放入stage中,其它的模塊作為操作者來接收stage中的事件,然后觸發操作。這些模塊當需要的時候,反過來也會將事件排隊放入stage隊列中。
  
  圖6顯示了擁有一個stage的解藕模塊
  
 實例解析:設計一個完全可擴展的應用(圖六)
  圖6. 用stage解藕

  
  MantaRay項目將stage的概念提升到了更高層次。模組通過工廠(factory)對象得到一個stage的引用。工廠會動態地生成合適的實現,這依靠于stage是在一個分布式環境中還是在內存中。
  
  幾個模塊(或同一模塊的幾個實例)可以將他們自己作為操作者加到同一個stage上,但是一個事件會且只會送給一個操作者。一個事件可以是實現了標記性接口Serializable的任意對象。大多數對象能被序列化,但像Socket和OutputStream這樣的對象不能被序列化,因為實際上他們不能通過網絡傳遞。你可以把這個標記性接口給任意對象加上而不需要增加任何方法。
  
  在WebMonitor的例子中,GUI模組通過一個stage將一個請求發送給了引擎,讓其監聽一個URL。引擎將它們自己注冊為stage的操作者,stage反過來由于其中間層的角色也成為了一個軟件負載的平衡者。
  
  Dispatcher
  
  dispatcher與一個stage非常類似,但有一個顯著區別。與stage事件有且只有一個操作者不同,一個dispatcher事可以被送給所有的操作者,假如它們將自己注冊到了dispatcher上。這樣,一個dispatcher就作為一個一對多的中間層來工作。
  
  圖7 顯示了使用了dispatcher的解藕模組
  
實例解析:設計一個完全可擴展的應用(圖七)
  圖7. 用dispatcher解藕

  
  應用到事件上的相同的角色被dispatcher分發,就像排隊到stage上的事件一樣。另外,算法通過工廠(和用來獲得stage的引用的一樣)來得到dispatcher的引用。
  
  在WebMonitor例子中,引擎通過dispatcher告知GUI關于所監控的URL狀態改變的信息。所有的GUI模塊將他們自己都注冊為發布者的操作者,他們都會得到所監聽URL狀態改變的通知。
  
  下面是一個簡短的代碼示例:GUI、引擎如何與stage、dispatcher集成在一起:
  
  GUI代碼
  
  import org.mr.api.blocks.ScalableDispatcher;  import org.mr.api.blocks.ScalableFactory;  import org.mr.api.blocks.ScalableHandler;  import org.mr.api.blocks.ScalableStage;  ...  public class WebMonitorGui implements ActionListener  , ScalableHandler{  // 輸入的url被檢查  JTextField urlInput;     // 從外面指向引擎的stage  public ScalableStage engineStage;     // 從引擎而來的內置dispatcher  public ScalableDispatcher guiDispatcher;  /** * GUI分別得到一個對內的dispatcher和對外的stage的引用,* 分布式的參數被傳至這些對象的工廠。 * @param distributed. 假如布爾值為真則表示這個范例是運行在 * 分布式的環境中,引擎是分布在了不同的虛擬機上。 */  public WebMonitorGui(boolean distributed){    // 從工廠中得到stage    engineStage = ScalableFactory.getStage("engine"      , distributed);    // 從工廠中得到dispatcher    guiDispatcher = ScalableFactory.getDispatcher(      "gui", distributed);        // 將這個對象注冊為所有即將發生事件的處理器    guiDispatcher.addHandler(this);  }    /**   * 開始SWING GUI   */  public void startGUI(){//確信我們已經有了不錯的GUI    ..} //開始GUI    /**   * 當用戶把URL的輸入通過stage送到引擎時,這個方法被調用。   */  public void actionPerformed(ActionEve

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 莱西市| 绥化市| 富宁县| 桐柏县| 金堂县| 马边| 大荔县| 泸溪县| 方城县| 定结县| 永吉县| 胶南市| 双鸭山市| 泰顺县| 荥阳市| 涡阳县| 鸡东县| 昌平区| 都匀市| 衡东县| 电白县| 溧阳市| 囊谦县| 利辛县| 简阳市| 克什克腾旗| 龙泉市| 太康县| 龙陵县| 铜梁县| 广南县| 虞城县| 盘锦市| 扎兰屯市| 拜泉县| 华阴市| 西林县| 左云县| 玉溪市| 大方县| 旅游|