3.6.3 如何实现集群管理

对于像淘宝这样上万台服务器集群环境的大型互联网应用,通常我们面临这样一种需求:我们需要一个集群管理者管理集群里的服务器,同一个集群中任何一台服务器宕机,其他服务器都能感知。如果是集群管理者宕机,集群中所有的服务器不能受任何影响,能实时切换到备份管理者上提供服务。

这个demo演示了如何利用Fourinone用简单几行代码实现上述功能:

❏ GroupManager:是一个集群管理者,它有master和slave两个实例,实际上你可以建立任意多的slave。

❏ GroupServer:代表一个集群中的server,它启动后会注册自己的信息到集群管理者,然后监控集群中其他机器的状况并实时反馈。它使用一个getLastest的API,这个API可以返回最新的集群状况,如果不是最新的就返回null。

  1. pl.create("group", args[0], args[0], AuthPolicy.OP_ALL, true);

❏ 上面的方法进行节点的注册,其中前3个参数分别是domain、node、value,AuthPolicy.OP_ALL表示该节点的权限为公共,也就是可以被其他进程修改删除,true代表它是个保持连接节点,如果失去连接,该节点会被删除。

运行步骤:

1)启动GroupManager进程,输入参数分别为M,代表master,结果如图3-13所示:

  1. java -cp fourinone.jar; GroupManager M

3.6.3 如何实现集群管理 - 图1

图3-13 GroupManager M

2)启动GroupManager进程,输入参数分别为S,代表slave,结果如图3-14所示:

  1. java -cp fourinone.jar; GroupManager S

3.6.3 如何实现集群管理 - 图2

图3-14 GroupManager S

3)启动3个GroupServer进程,每次输入参数分别为"one,two,three"代表3台集群server(它访问master的IP端口已经在配置文件指定),结果如图3-15所示。

  1. java -cp fourinone.jar; GroupServer one
  2. java -cp fourinone.jar; GroupServer two
  3. java -cp fourinone.jar; GroupServer three

3.6.3 如何实现集群管理 - 图3

图3-15 GroupServer

观察每个GroupServer进程里的输出,每个进程窗口都会有集群里所有服务器的信息输出,可以关掉其中一个进程模拟一个GroupServer宕机,此时其他两个GroupServer进程会实时输出集群更新信息,请再关掉master进程模拟GroupManager宕机,会发现两个GroupServer进程会即时选取slave为新的领导者,请把刚才关掉的一个GroupServer进程恢复,会发现所有GroupServer在master宕机情况下,也能实时得到集群的最新信息。

下面我们演示这一系列操作:

1)关掉GroupServer three,如图3-16所示。

3.6.3 如何实现集群管理 - 图4

图3-16 关闭GroupServer

可以看到,GroupServer three关闭后,GroupServer one和GroupServer two都输出了集群更新信息。

2)再关掉GroupManager master,如图3-17所示。

3.6.3 如何实现集群管理 - 图5

图3-17 关闭GroupManager

可以看到,当GroupManager master关闭时,GroupManager slave成为集群管理的领导者,并且GroupServer one和GroupServer two都切换到GroupManager slave上。

3)恢复GroupServer three,如图3-18所示。

3.6.3 如何实现集群管理 - 图6

图3-18 恢复GroupServer

从上面可以发现,虽然GroupManager master挂了,但是GroupServer three重新加入集群,GroupServer one和GroupServer two仍然可以通过GroupManager slave感知到集群的状况。

3.6.3 如何实现集群管理 - 图7注意

在集群管理或者集群配置信息等应用中,对及时性要求较高,可以将心跳时间调整得快些,避免延迟。比如将默认的3000毫秒改为1000毫秒或者其他值,根据自己的服务器性能和网络质量等因素去定:

  1. <HEARTBEAT>1000</HEARTBEAT>(配置文件中Park部分)

下面是demo源码:

  1. // GroupManager
  2. import com.fourinone.BeanContext;
  3.  
  4. public class GroupManager
  5. {
  6. public static void main(String[] args)
  7. {
  8. String[][] master = new String[][]{{"localhost","1888"},{"localhost", "1889"}};
  9. String[][] slave = new String[][]{{"localhost","1889"},{"localhost", "1888"}};
  10.  
  11. String[][] server = null;
  12. if(args[0].equals("M"))
  13. server = master;
  14. else if(args[0].equals("S"))
  15. server = slave;
  16.  
  17. BeanContext.startPark(server[0][0],Integer.parseInt(server[0][1]), server);
  18. }
  19. }
  20.  
  21. // GroupServer
  22. import com.fourinone.BeanContext;
  23. import com.fourinone.ParkLocal;
  24. import com.fourinone.ObjectBean;
  25. import com.fourinone.AuthPolicy;
  26. import java.util.List;
  27.  
  28. public class GroupServer
  29. {
  30. public static void main(String[] args)
  31. {
  32. ParkLocal pl = BeanContext.getPark();
  33. pl.create("group", args[0], args[0], AuthPolicy.OP_ALL, true);
  34.  
  35. List<ObjectBean> oldls = null;
  36. while(true){
  37. List<ObjectBean> newls = pl.getLastest("group", oldls);
  38. if(newls!=null){
  39. System.out.println("Group:"+newls);
  40. oldls = newls;
  41. }
  42. }
  43. }
  44. }