程序故障如下:
服务端
程序启动后 能运行5天(都正常,网络故障,客户端断开后重连继续运行也没问题),
可是运行5天后客户端就全部断开了,自动连接,一连就断开(不断循环此过程了就),不知道怎么回事·
如果是线程问题的话, 怎么每次都是运行5天的样子,挂的时间很规律(一般启动后5天)
public void run() {
while (true) {
try {
Socket socket = server.accept();
synchronized (SocketDBServer.lock) {
socketMap.put(socket.getInetAddress().toString().substring(1), socket);//保存客户端IP
}
if(AutoMain.switchFlag) {
synchronized (AutoMain.obj) {
if (socketMap.size() >= BaseConfig.MIN_CONTROLSER_COUNT) {
AutoMain.switchFlag = false;
AutoMain.obj.notify();
}
}
}
SocketDBServerThread dbserver = new SocketDBServerThread(socket);
logger.info("new SocketDBServerThread(socket)");
new Thread(dbserver).start();
logger.info("new Thread(dbserver).start();");
} catch (IOException e) {
logger.error("SocketDBServer.run() server.accept()", e);
}
}
}
还有个疑问,程序挂掉后(客户端在不停的连接中...),我在日志中发现 new Thread(dbserver).start(); 执行这句话居然用了5秒
 上面run方法里面 的语句偶尔会出现这种情况(执行一句话要几秒钟),是什么情况会造成执行一句话要这么久?
CPU满了? 内存满了?唉纠结很久了,有没有经验的朋友 指点下!
而且现在很恶心,我该改了点东西,测试,又测试不出来,非要跑那么就才出问题·

解决方案 »

  1.   

    换用线程池,别每次都new Thread().
      

  2.   

    socketMap的数据什么时候清除的?已经断开连接的ip还存在吗?
    建议使用线程池,每次都new一个线程,相当消耗系统资源
    两句log相差5秒,那说明CPU可能出于峰值,没有空暇分配给线程执行
    光从你这点代码来看,CPU和内存都存在一定的问题
      

  3.   

    我客户端没有很多的连接,就4 5个固定的监控点(开启后就一直是长连接),所以没用连接池。
    socketMap 里面的数据是,我客户端断开连接的死后清除的·catch (IOException e) {
    String key = socket.getInetAddress().toString().substring(1);
    synchronized (SocketDBServer.lock) {
    if(SocketDBServer.socketMap.get(key) == socket) {
    SocketDBServer.socketMap.remove(key);
    }
    }
    logger.info("监控机:" + socket.getInetAddress() + " 断开连接    监控机数量:" + SocketDBServer.socketMap.size() + "Socket信息:" + socket.toString(), e);
    closeResources();
    }
      

  4.   

    不过我内存中还有一个大的容器,存储所有监控节点返回的数据的, 是不是那里没有很好的释放掉没用的数据造成的?
    是不是当CPU 内存达到一定负载的时候,程序就执行很慢了啊? 每执行一句都可能需要几秒钟·
    这样的话, 因为我客户端读取数据有个超时时间, 过段时间服务器如果没响应客户端就会 自动断开连接 然后重连, 这样就造成现在这种情况?(不断重连,连上就掉)
      

  5.   

    以前出现这种情况的时候 我看CPU使用率 是100%的· 内存的话 没有注意·
      

  6.   

    CPU 100% 肯定就有问题,应该是有死循环,要不就什么地方不正确.
    怎么着也要阻塞在网络IO上.
    楼主关注一下程序的内存利用情况,程序死是否与此有关.
      

  7.   

    用Oracle公司的JRMC工具测测内存喏,官网上有免费下载的,可以很清楚的观察到内存使用量、内存增量等。
      

  8.   

    所有的东西都放map里,内存会不会溢出??
      

  9.   

    我内存中有这么一个集合 一直存放数据的·
    ConcurrentHashMap<被监控机IP, ConcurrentHashMap<监控机IP, 监控结果的对象>> /**
     * 添加监控结果数据
     * @param monitorResult  监控结果  
     */
    public void add(MonitorResult monitorResult) {
        if(monitorResult == null){ return; }
    synchronized (AutoMain.lock) {
    //根据 被监控IP 获得各监控机返回的数据集Map
    ConcurrentHashMap<String, MonitorResult> resultData = map.get(monitorResult.getCacheServerIp());
    if (resultData != null) {
    //更新最新监控结果
    resultData.put(monitorResult.getMonitorServerIp(), monitorResult);
    }
    }
    }resultData.put(monitorResult.getMonitorServerIp(), monitorResult);
    这样的话应该不会 存在垃圾数据吧?
    然后我另外 有一个线程定时去取这个集合, 分析这些数据 做处理。
      

  10.   

    resultData.put(monitorResult.getMonitorServerIp(), monitorResult);
    是所有结果都放里面,但是只保存了最新的结果, 以前旧的结果我全丢弃了·
      

  11.   

    当前内存信息:init = 130596288(127535K) used = 369232872(360578K) committed = 418775040(408960K) max = 1858600960(1815040K)
    这是我实时打印的 内存信息·
    程序运行过程中 used = 369232872(360578K) committed = 418775040(408960K) 这2个会不断提升·
    刚开始 used = 20几M  committed也一样, 现在跑了1天多点, 都300多的 400多M了·
    程序挂的时候 都是1G多·
      

  12.   

     synchronized (SocketDBServer.lock) {
                    socketMap.put(socket.getInetAddress().toString().substring(1), socket);//保存客户端IP
                }
    这句有点吓人,线程会不断的put,消耗大
    可以改改 if(!socketMap.get(socket.getInetAddress().toString().substring(1), )){
         socketMap.put(socket.getInetAddress().toString().substring(1), socket);//保存客户端IP
    }
    还有就是
    new Thread(dbserver).start();//不知要执行多少次,开启多少线程,消耗可想而知了
      

  13.   


    //线程延时器,比while(true)性能好
    ScheduledExecutorService scheduled = Executors.newSingleThreadScheduledExecutor();
    ScheduledFuture future = scheduled.scheduleWithFixedDelay(this, 0, 100,TimeUnit.SECONDS);//线程池,可有效管理线程。
    ExecutorService  executors = new ThreadPoolExecutor(20, 20, 0L,
    TimeUnit.MILLISECONDS,
    new DefaultedOfferTimeoutBlockingQueue<Runnable>(5, 86400,TimeUnit.SECONDS));
    executors.execute(new TaskThread());
    线程内部代码肯定还存在问题,导致内存泄露,对象用完之后要释放。