Java類中熱替換的概念、設計與實現(4)

來源:互聯網
上載者:User

    線上升級系統的設計原則

    在上小節中,我們給出了一個Java類熱替換的執行個體,掌握了這項技術,就具備了實現線上升級系統的基礎。但是,對於一個真正的產品系統來說,升級本省就是一項非常複雜的工程,如果要線上升級,就會更加複雜。其中,實作類別的熱替換隻是最後一步操作,線上升級的要求會對系統的整體設計帶來深遠的影響。下面我們來談談線上升級系統設計方面的一些原則:

    ◆在系統設計一開始,就要考慮系統的哪些部分是需要以後線上升級的,哪些部分是穩定的

    雖然我們可以把系統設計成任何一部分都是可以線上升級的,但是其成本是非常高昂的,也沒有必要。因此,明確地界定出系統以後需要線上升級的部分是明智之舉。這些部分常常是系統商務邏輯規則、演算法等等。

    ◆設計出規範一致的系統狀態轉換方法

    替換一個類僅僅是線上升級系統所要做的工作中的一個步驟,為了使系統能夠在升級後正常運行,就必須保持升級前後系統狀態的一致性。因此,在設計時要考慮需要線上升級的部分所涉及的系統狀態有哪些,把這些狀態設計成便於擷取、設定和轉換的,並用一致的方式來進行。

    ◆明確出系統的升級控制協議

    這個原則是關於系統線上升級的時機和流程式控制制的,不考慮系統的當前運行狀態就貿然進行升級是一項非常危險的活動。因此在系統設計中,就要考慮並預留出系統線上升級的控制點,並定義清晰、明確的升級協議來協調、控制多個升級實體的升級次序,以確保系統在升級的任何時刻都處在一個確定的狀態下。

    ◆考慮到升級失敗時的回退機制

    即使我們做了非常縝密細緻的設計,還是難以從根本上保證系統升級一定是成功的,對於大型分布式系統來說尤其如此。因此在系統設計時,要考慮升級失敗後的回退機制。

    線上升級系統執行個體

    首先,我們來簡單介紹一下這個執行個體的結構組成和要完成的工作。在我們的例子中,主要有三個實體,一個是升級控制實體,兩個是工作實體,都基於ActiveObject實現,通過命令訊息進行通訊(關於ActiveObject的詳細資料,可以參見作者的另外一篇文章“構建Java並行存取模型架構”)。

    升級控制實體以RMI的方式對外提供了一個管理命令介面,用以接收外部的線上升級命令。工作實體有兩個訊息佇列,一個用以接收分配給它的任務(我們用定時器定時給它發送任務命令訊息),我們稱其為任務隊列;另一個用於和升級控制實體互動,協作完成升級過程,我們稱其為控制隊列。工作實體中的任務很簡單,就是使用我們前面介紹的Foo類簡單地列印出一個字串,不過這次字串作為狀態儲存在工作實體中,動態設定給Foo類的執行個體的。升級的協議流程如下:

    當升級控制實體接收到來自RMI的線上升級命令時,它會向兩個工作實體的任務隊列中發送一條準備升級訊息,然後等待回應。當工作實體在任務隊列中收到準備升級訊息時,會立即給升級控制實體發送一條準備就緒訊息,然後切換到控制隊列等待進一步的升級指令。升級控制實體收齊這兩個工作實體發來的準備就緒訊息後,就給這兩個工作實體的控制隊列各發送一條開始升級訊息,然後等待結果。工作實體收到開始升級訊息後,進行實際的升級工作,也就是我們前面講述的熱替換類。然後,給升級控制實體發送升級完畢訊息。升級控制實體收到來自兩個工作實體的升級完畢訊息後,會給這兩個工作實體的控制隊列各發送一條繼續工作訊息,工作實體收到繼續工作訊息後,切換到任務隊列繼續工作,升級過程結束。主要的程式碼片段如下(略去命令訊息的定義和執行細節):

 
  1. // 升級控制實體關鍵代碼 
  2. class UpgradeController extends ActiveObject{  
  3.     int nready  = 0;  
  4.     int nfinished = 0;  
  5.     Worker[] workers;  
  6.     ......  
  7.     // 收到外部升級命令訊息時,會觸發該方法被調用 
  8.     public void askForUpgrade() {  
  9.         for(int i=0; i<workers.length; i++)  
  10.             workers[i].getTaskQueue().enqueue(new PrepareUpgradeCmd(workers[i])); 
  11.     }  
  12.  
  13.     // 收到工作實體回應的準備就緒命令訊息時,會觸發該方法被調用 
  14.     public void readyForUpgrade(String worker_name) {  
  15.         nready++;         
  16.         if(nready == workers.length){  
  17.             for(int i=0; i<workers.length; i++)  
  18.                 workers[i].getControlQueue().enqueue(new  
  19.                     StartUpgradeCmd(workers[i]));  
  20.         }       
  21.     }  
  22.  
  23.     // 收到工作實體回應的升級完畢命令訊息時,會觸發該方法被調用 
  24.     public void finishUpgrade(String worker_name) {  
  25.         nfinished++;  
  26.         if(nfinished == workers.length){  
  27.             for(int i=0; i<workers.length; i++)  
  28.                 workers[i].getControlQueue().enqueue(new  
  29.                     ContineWorkCmd(workers[i]));  
  30.  
  31.         }  
  32.     }  
  33.      
  34.     ......  
  35.  
  36. }  
  37.  
  38. // 工作實體關鍵代碼 
  39. class Worker extends ActiveObject{  
  40.     UpgradeController ugc;  
  41.     HotswapCL hscl;  
  42.     IFoo foo;  
  43.     String state = "hello world!";  
  44.      
  45.     ......  
  46.     
  47.     // 收到升級控制實體的準備升級命令訊息時,會觸發該方法被調用 
  48.     public void prepareUpgrade() {  
  49.         switchToControlQueue();  
  50.         ugc.getMsgQueue().enqueue(new ReadyForUpdateCMD(ugc,this));  
  51.     }  
  52.  
  53.     // 收到升級控制實體的開始升級命令訊息時,會觸發該方法被調用 
  54.     public void startUpgrade(String worker_name) {  
  55.         doUpgrade();  
  56.         ugc.getMsgQueue().enqueue(new FinishUpgradeCMD(ugc,this));  
  57.     }  
  58.  
  59.     // 收到升級控制實體的繼續工作命令訊息時,會觸發該方法被調用 
  60.     public void continueWork(String worker_name) {  
  61.         switchToTaskQueue();  
  62.     }  
  63.  
  64.     // 收到定時命令訊息時,會觸發該方法被調用 
  65.     public void doWork() {  
  66.         foo.sayHello();     
  67.     }  
  68.  
  69.     // 實際升級動作 
  70.     private void doUpgrade() {  
  71.         hscl = new HowswapCL("../swap", new String[]{"Foo"});  
  72.         Class cls = hscl.loadClass("Foo");  
  73.         foo = (IFoo)cls.newInstance();  
  74.         foo.SetState(state);  
  75.     }  
  76. }  
  77.  
  78. //IFoo 介面定義 
  79. interface IFoo {  
  80.     void SetState(String);  
  81.     void sayHello();  

在Foo類第一個版本的實現中,只是把設定進來的字串直接列印出來。在第二個版本中,會先把設定進來的字串變為大寫,然後列印出來。例子很簡單,旨在表達規則或者演算法方面的升級變化。另外,我們並沒有提及諸如:訊息逾時、升級失敗等方面的異常情況,這在實際產品開發中是必須要考慮的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.