前几天, 写完一个幕后扫描程序, 由于业务存在多对多的站点关系, 为了程序逻辑简单化, 牺牲掉一些硬件资源 来动态创建N个线程池(是池子哦).
结果悲剧发现: 公司服务器资源耗尽, 其它应用都跑不了, 系统宕机, 运维同事用不了命令.
幸好, 幸好, 有经验丰富的压力测试的同事帮顶住了, 结果2分钟解决BUG, 哈哈!
题外话, 技术组人员配置一定要有经验丰富的~
1.程序日志, 没有任何异常, 因为都是些普通业务, JMX 重型编程 没有在本程序中使用.
2.系统日志:
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
automount[4228]: expire_proc: expire thread create for /misc failed
automount[4228]: expire_proc: expire thread create for /net failed
.......................
fork: Resource temporarily unavailable
一看 fork. 我就直接想起 fork/join 并发编程的模型, 也不知道两者是不是有直接关系.
同事, 提醒线程太多 撑爆了系统!
我和同事都认为 Java GC 会[b]直接[/b]回收ExecutorService 对象啊! 事实相反, thread 一多也是很耗资源!
Java Doc :
/*
* An unused ExecutorService should be shut down to allow reclamation of its resources....
* @since 1.5
* @author Doug Lea
*/
程序结构,修改BUG后:
public class ChecksumsCalculatorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
AsynService calculator = new AsyncServiceImpl(siteId, nodeName, someInfos,
requestCallbackImpl);
Thread t = new Thread(calculator);
t.start();
}
}
public class AsyncChecksumsServiceImpl implements AsyncChecksumsService {
private ExecutorService threadPool; // 悲剧就在这.
//init in construct.
public void run() {
try{
// threadPool do something
// get Future
}catch(...){
}finally{
/**let GC do its work*/
threadPool.shutdown();
threadPool = null;
}
}
}
[b]总结:
大资源由原来的三个类型 Stream , Connection, GUI 图形对象,
现在增加一个类型interface ExecutorService,
此四类都要用完都要关闭资源!
[/b]
悲剧源自数据量巨大, GC 不能回收用完的池子, 实战大数据并发编程才开始不久!
经验不足, 只能救助于书了!
并发编程推荐, 读英文好!
[size=large][b]Addison.Wesley.Java.Concurrency.in.Practice.May.2006.[/b][/size]
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
有应聘"Java工程师/架构师", 请发邮件至:
[email protected], 并取得联系.
工程师招聘,岗位见: [url]http://job.youzan.com[/url] 请联系我:
[email protected]