Chapter1 在云上架构你的应用

实验条件:

       虚拟机管理器 VirtualBox

      两个虚拟机:都是XP,一个命名为"XP_JPetStore",一个命名为"XP_JPetStore_Client",其实"XP_JPetStore_Client"是由"XP_JPetStore"完全拷贝得到。

                             两具虚拟机里面都下载装了Tomcat 8应用服务器相应于xp上的运行程序,且也下载了宠物商店(JPetStore)应用程序mybatis-jpetstore-6.0.0-bundle.zip,当然也下载了

                              Java JDK(因为Tomcat要运行需要有Java环境),且Tomcat 8要运行在JDK7版本及以上,所以Java JDK为版本7,且虚拟机里的操作系统已配置好了java环境;

      VirtualBox对两个虚拟机的网络模式设置都为Host Only模式(总之,目的是:使主机操作系统能ping通两个虚拟机,然后我发现这个模式下达到了要求),VirtualBox在主机上的

                   HostOnly的ip设为192.168.56.1,两个虚拟机的ip分别为:192.168.56.102和192..168.56.103,网关都为192.168.56.1,网络掩码当然都是255.255.255.0

    主机:Windows XP系统,安装了JMeter测试工具(Windows下JMeter启动\bin\jmeter.bat)

实验步骤:

一、部署网页应用程序(网站)

1、安装Tomcat 8

      将下载的Tomcat 8的zip文件解压到相应目录,为了能进入Tomcat 8的manager管理网页并部署宠物商店应用程序mybatis-jpetstore-6.0.0.war,需要先编辑Tomcat 8conf目录下的tomcat-users.xml,加入以下有效代码

<tomcat-users>
     <role rolename="manager-gui" />
     <user username="用户名" password="密码"  roles="用户名,manager-gui" />
</tomcat-users>

2、如果上面实验条件顺利,并且Tomcat 8安装正确的话,接下来,部署宠物商店应用程序mybatis-jpetstore-6.0.0.war,浏览器中(无论是主机上还是虚拟机里的OS上)打开http://192.168.56.102(客户机的IP):8080(8080中Tomcat默认的端口)/,可以进入Tomcat管理页面,单击Manager,输入上面配置的用户名、密码,可进入管理页面,然后点击Deploy(部署)Tab,进入后点击Browse按钮,找到我们解压mybatis-jpetstore-6.0.0-bundle.zip得到的mybatis-jpetstore-6.0.0.war,然后部署;

   如果安装存在问题,查看Tomcat 8的logs\catalina.***..log

3、现在在浏览器中输入http://192.168.56.102:8080/mybatis-jpetstore-6.0.0/actions/Action.htm即可看到宠物商店的网页

二、对网站进行压力测试

       假设开始时,虚拟机的内存设为256M,运行jmeter目录\bin\jmeter.bat得到测试效果(注意过程是:右击测试计划->添加Threads(Users)->线程组……,另外,在刚才的线程组上右击添加了Sampler->Http请求后,如下)

运行jmeter目录\bin\jmeter.bat得到测试效果

256M虚拟机时

现虚拟机的内存设为512M,运行jmeter目录\bin\jmeter.bat得到测试效果

三、云计算的理念来提高网站的响应速度

      原理是:将网站部部署在两台主机(这里是两台虚拟机)上,当网站的访问量太大——表现为Tomcat的负载过重(也即内存、CPU、网络带宽消耗很重时),使两台机子上的应用服务器一起工作,然后,在网站应用程序的逻辑功能前加一个“导购”似的逻辑程序来分流访问——负载均衡。

      说的更具体点:因为Tomcat本身是使用Java语言实现,所以,通过监控Java虚拟机,可以达到监控Tomcat的目的。JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。Java虚拟机本身就内建了一些JMX管理模块,可以监控内存以及CPU的使用情况(在其java目录下\bin\jconsole.exe即是提供了图形化的监控界面)。我们根据Tomcat使用的内存来作相应策略——例如,当Tomcat使用的内存超过50%时,启动第二台虚拟机XP_JPetStore_Client并启动同样的Tomcat来分流负载

    为使主机能监控虚拟机里运行的Tomcat 相应的负载,需要编辑Tomcat安装目录中的catalina.bat文件(这是一个Windows脚本,用来启动Tomcat应用服务器),具体在下图中有相应标注说明:

即在catalina.bat文件中一大堆rem 注释后、各函数之前加入set JMX_REMOTE_CONFIG=-Dcom.sun.management.jmxremote ……等内容,然后重新启动虚拟机里的Tomcat,在配置好Java环境变量的主机上的命令终端输入jconsole,然后选择远程连接,输入虚拟机IP:端口(这里我的端口设置为9004),即可得到上述监控界面

现在,我们根据VirtualBox的终端操作命令和JMX接口,根据Tomcat运行时的负载(内存消耗)来择机启动第二台虚拟机,这里,监控程序(远程监控Tomcat运行消耗内存)如下:

/**
 * @author xiaoyao3857
 *
 */
package com.qihua.cloud;

import java.io.IOException;
import java.net.MalformedURLException;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JMXClient {
	public JMXClient(){
		super();
	}
	public static void main(String[] args) throws Exception{
		String urlForJMX ="service:jmx:rmi:///jndi/rmi://192.168.56.102:9004/jmxrmi";
		MBeanServerConnection jmxServerConnection = JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX),null).getMBeanServerConnection();
		try{
			String[] domains = jmxServerConnection.getDomains();
			for(String domain:domains){
				System.out.println(domain);
			}
			ObjectName memory = new ObjectName("java.lang:type=Memory");
			CompositeDataSupport comp = (CompositeDataSupport)jmxServerConnection.getAttribute(memory, "HeapMemoryUsage");
			double max = (Long)comp.get("max");
			double used = (Long)comp.get("used");
			System.out.println(used/max);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	public static double getMemoryUsage(){
		String urlForJMX="service:jmx:rmi:///jndi/rmi://192.168.56.102:9004/jmxrmi";
		MBeanServerConnection jmxServerConnection = null;
		double memoryUsage = 0;
		try{
			jmxServerConnection = JMXConnectorFactory
					.connect(new JMXServiceURL(urlForJMX),null)
					.getMBeanServerConnection();
		}catch(MalformedURLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		try{
			String[] domains = jmxServerConnection.getDomains();
			for(String domain:domains){
				System.out.println(domain);
			}
			ObjectName memory = new ObjectName("java.lang:type=Memory");
			CompositeDataSupport comData = (CompositeDataSupport)jmxServerConnection.getAttribute(memory, "HeapMemoryUsage");
			double max = (Long)comData.get("max");
			double usage = (Long)comData.get("used");
			memoryUsage = usage/max;
		}catch(Exception e){
			e.printStackTrace();
		}
		return memoryUsage;
	}
}

上面程序得到堆内存的使用率

下面程序是通过Java语言实现启动与关闭虚拟机的操作

/*
 * Author xiaoyao3857

 * 用JAVA根据VirtualBox来操作虚拟机 "XP_JPetStore_Client"(它是在VirtualBox中已建好的,
 * 只是初始状态,只是初始状态是关闭的)
 * 
 * 根据VirtualBox的帮助文档中关于VBoxMange的章节和查阅资料,加上先实际命令行操作试验:
 * 			它是先用VBoxMange startvm vmname|vm_guid 来开启虚拟机
 * 			接下来再使用
 *          VBoxManage --nologo guestcontrol "My VM" execute --image "/bin/ls"
          --username foo --passwordfile bar.txt --wait-exit --wait-stdout -- -l /usr

VBoxManage --nologo guestcontrol "My VM" execute --image "c:\\windows\\system32\\ipconfig.exe"
          --username foo --passwordfile bar.txt --wait-exit --wait-stdout
 * 目前OperateVM先如代码中那样写着:具体没有用到用户名、密码等,因为没有
 * 找到VirtualBox中对于使用用户名、密码来完全使Guest Operating System运行的
 */
package com.qihua.cloud.util;

public class OperateVM {
	//public void startVM(String userName,String passwd,String url,String dataStore,String path,String VMName){
		
	//}
	public  static void startVM(String VMName) {
		//start Virtual Machine
		ExecuteCommand.execute("C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage startvm " + VMName);
		//run the Virtual Machine's Tomcat
		ExecuteCommand.execute("C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage --nologo guestcontrol " + VMName
				+ " execute --image \"E:\\apache-tomcat-8.0.0-RC5-windows-x86\\apache-tomcat-8.0.0-RC5\\bin\\startup.bat\" --username HuaHero --password 123 --wait-exit --wait-stdout" );
	}
	public static void stopVM(String VMName){
		ExecuteCommand.execute("C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage controlvm " + VMName + " poweroff");
	}
}
/*
 * Author xiaoyao3857
 * execute command
 */

package com.qihua.cloud.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class ExecuteCommand {
	public static void execute(String cmd){
		try{
			Runtime rt = Runtime.getRuntime();
			Process pr = rt.exec(cmd);
			BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
			String line = null;
			while((line = input.readLine())!=null){
				System.out.println(line);
			}
			int exitVal = pr.waitFor();
			System.out.println("Exited with error code" + exitVal);
		}catch(Exception e){
			System.out.println(e.toString());
			e.printStackTrace();
		}
	}
}

那么,集成监控与虚拟机操作代码,当Tomcat使用内存超过50%时我们启动第二台虚拟机及其相应服务。程序如下:
/*
 * Author xiaoyao3857
 * 虚拟机调度器
 */
package com.qihua.cloud;

import com.qihua.cloud.util.OperateVM;

public class VMscheduler {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		while(true){
			double memoryUsage = 0;
			try{
				memoryUsage = JMXClient.getMemoryUsage();
				//每隔1分钟查看一次内存使用情况
				Thread.sleep(1*60*1000);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			if(memoryUsage > 0.5){
				OperateVM.startVM("XP_JPetStore_Client");
			}else{
				OperateVM.stopVM("XP_JPetStore_Client");
			}
		}
	}

}
整个程序架构为:

实验结果为:



    当然,上面虚拟机启动出现问题是由于我的主机内存不足,关掉一些程序后,点击虚拟机里“确定”按钮就正常了。

实验中,为了早些观察结果:我的程序是每一分钟查看一次内存使用情况,并且,为了验证,可以将>0.5条件改为0.4条件,并且,可以尝试关掉Tomcat,看我们的虚拟机调度程序是否关闭我们打开的虚拟机——总之,这样可以来大体上验证我们的程序是否按我们想走的逻辑正常进行。


有了上面的工作,接下来的后续工作是:实现负载均衡——即当访问网站的流量太大时,我们新开了主机(或虚拟机)同样的Tomcat服务器,然后在流量进入服务器前加一个负载均衡器(起生活中“导购”的作用),实现途径是:1、可水平扩展;2、可垂直扩展


本博客只记概要流程,在实验中某一过程如有问题,可以利用搜索引擎找到解决办法,当然,也欢迎留言探讨

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐