在线升级系统实例
首先,我们来简单介绍一下这个实例的结构组成和要完成的工作。在我们的例子中,主要有三个实体,一个是升级控制实体,两个是工作实体,都基于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.