本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Dreamcode/archive/2010/05/26/5624429.aspx
大量并发的应急处理方案与实践1——异步处理
往往我们会遇到这样的问题,以前一直运行良好的系统由于突然遇到大量并发访问而崩溃,这时你的客户和老板全都急上了房。情况紧急重新改造系统架构非常困难需要时间。这时你非常后悔,如果当时采用分布式架构那么现在只要水平增加应用或数据服务器就好了,所有现存数据和应用也不会受到任何影响。关于系统架构可参考我的另一篇文章:《开餐馆与做软件——如何提高大型网站性能》http://blog.csdn.net/Dreamcode/archive/2009/09/10/4540153.aspx
现在我们只好采用一些应急的解决方案。 举例来说,一个房间只能容纳500人,现在突然来了1000人这时我们该怎么办?
办法有两个:一是增加房间面积,这个办法如同水平增加应用或数据服务器,需要对架构进行重新设计,因此将涉及很多问题,或许并不比重新造省时间。另一个办法就是让客人排队,当屋里有人出去,再让别人进来,即异步处理。
异步处理,当资源不足的情况下对已经到来的访问请求并不马上处理而是让这些请求排队等候,直到有可用的资源再进行处理。这种办法的代价就是时间,不能及时返回处理结果。但是当我们没有条件改造房屋的时候这是唯一的办法。
现在有个问题,我们让客人在哪里排队,大厅(硬盘)还是门口(内存)。答案似乎很明显,哪里离房间近最好就在哪里等,但是,速度快的地方往往空间不富裕。将用户请求以某种方式先保存在硬盘上是一种比较常用的方法,当然也因此多了一步将数据加载到内存地过程。
在内存中将数据排队的方法,可使用数组,哈希表,链表等数据结构,也可使用消息队列等现成的组件如ActiveMQ 。如我们使用一个单例模式的Map 对象,保存来自多个并发的请求。
import java.util.Map;
public class TestMap {
private volatile static TestMap singleton=null;
private static Map testmap = null;
private TestMap(){}
public static TestMap getInstance()
{
if(singleton==null){
synchronized(TestMap.class)
{
singleton=new TestMap();
}
}
return singleton;
}
public Map getTestmap() {
return testmap;
}
public void setTestmap(Map testmap) {
TestMap.testmap = testmap;
}
}
在硬盘中排队,就是将数据直接写到硬盘里,例如在Java 中可将对象直接保存到硬盘中,代码如下:
public static boolean writeObject(String filePath, Object entity)
{
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(fos);
oos.writeObject(entity);
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
public static Object readObject(String filePath)
{
Object entity = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ObjectInputStream ois;
try {
ois = new ObjectInputStream(fis);
try {
entity = ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return entity;
}
最后我们需要一个监控模块(如一个线程)进行调度, 例如:
public class testThread implements Runnable{
private static long interval = 3000; //循环间隔
@Override
public void run(){
while(true)
{
... //这里是需要执行的代码
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}