情况是: 内外网 物理隔离,中间数据穿透 只能通过隔离装置 ,并且只能过SQL。
功能描述:外网将请求写入内网数据库 请求表,内网起扫描线程查询请求表(频率是0.5秒),将请求解析 通过Websrvice调用程序,调用结果写入 响应表,外网的扫描线程扫描响应表(频率是0.5秒), 然后将结果放入缓存供最开始调用方取数据。
扫描程序中使用了 java多线程,线程池 来处理请求和响应。问题是:外网扫描 和内网扫描程序 会出现进程僵死的状态,然后就不能处理扫描功能了。
程序 请求量不是很大,高峰期每秒50个请求 ,程序 2天死一次。求大牛 指导,优化 实现这样的需求:
 为什么会进程僵死,而不是程序挂掉? 是否线程启用太多 ?
在此 之前 测试过 通过Oracle,对请求表建立触发器 调用存储过程,再调用Websrvice 但是丢失率比较高。有无类似的实现方式?
 Nosql有触发器吗?MySQL是否比较好处理这样的问题?
       

解决方案 »

  1.   

    描述比较简单,没看出啥具体问题。因为你用了线程池,所以不应该是线程太多的原因。
    不过你描述线程池的方式很奇怪,不应该是起一个线程加入池中,应该是增加一个任务然后扔给线程池。建议下次碰到僵死时,把JVM的线程执行栈导出来看看,就是ThreadDump;看看你的调度线程卡在什么位置,还是说调度线程已经消失。
    另外同时检查下数据库是否存在死锁情况。不知道你是怎么调度扫描线程的,不过建议把扫描线程和工作线程彻底分开。扫描线程启动后就不再结束,注意捕获所有异常,避免线程终止;
    扫描线程每次睡0.5秒后就查询一次请求队列,然后根据返回的结果集,每个创建一个任务,加入到线程池中;然后继续睡下一次0.5秒。
    如果要更安全点,就每次睡醒后,先检查下线程池堆积任务数量,如果太多了,就发出警告然后不再增加任何任务,以免恶化阻塞情况。
      

  2.   

    Oracle数据库产生死锁时,或者,同一个表的其他事务没有释放的时候,数据库连接会出现卡死的现象。楼主还是要将卡死时候的 线程占 都打印出来看看。以前项目当中,遇到程序卡死的时候,是出现了逻辑死锁。
    就是在使用线程池的时候,提交的任务对象中,自己调用了自己产生的Fuiture对象的get方法,
    该方法本来应该是其他(管理)线程来调用的,以获得任务的执行结果,
    并且,该方法,在任务没有完成的时候,会将主调线程阻塞。
      

  3.   

     调度扫描线程:
    where(true){
       // select xxx from task;
    }