页面树结构
转至元数据结尾
转至元数据起始

正在查看旧版本。 查看 当前版本.

与当前比较 查看页面历史

版本 1 下一个 »

目录
一、 线程信息的作用
二、 线程信息的使用场景
三、 怎么打印线程信息
四、 怎么分析线程信息


线程信息的作用

JVM由多个线程组成了一个进程,每个线程代表一个操作。线程信息主要用于分析当时整个服务器正在执行什么操作。

线程信息的使用场景

线程信息主要用于分析服务器宕机(因为假如服务器宕机,从线程可能可以看到死锁,某操作一直执行没有完成,如数据库查询语句没有返回)。
或某些操作服务器一直不响应的情况,如保存操作一直没有响应,查询报表没有响应之类的问题都可以通过线程看出来。

怎么打印线程信息

方法1

在系统没有宕机时,可以访问"系统监控"->"线程"获取线程信息

方法2

V62或V72以后的版本也可以访问应用服务器smartbi\mlogs-smartbi\threaddump目录获取最新的线程信息

注:之所以会有上面的线程信息,是因为默认启用自动打印线程信息,可以在系统选项中修改,见下图:

方法3

要求JDK版本为1.6及其以上版本。
1、在运行中打开cmd命令行窗口。
2、在cmd窗口进入JDK的bin目录下,执行jps获取进程信息,此处要保证执行的JDK是服务器使用的JDK。
     如命令行:cd C:\Smartbi_Insight\jdk\bin
                     jps
       
3、获取对应线程号,然后执行jstack +进程号 > 进程号.log 获取线程信息 :Tomcat显示的名称应该是Bootstrap;

4、可以在 C:\Smartbi_Insight\jdk\bin 目录下看到生成的线程文件。

方法4

1、通过CMD命令行窗口进入JDK的bin目录下
2、使用netstat -ano|find "访问的端口号"|find "LISTENING" 获取进程号(注意双引号是必须的)
     如访问smartbi的端口号是18080,则输入命令:netstat -ano|find "18080"|find "LISTENING"

3、再使用jstack 进程号 >进程号.log 获取线程信息,如果提示无法连接到JVM,可以增加-F参数强制生成jstack -F 进程号 >进程号.log
上边截图获取到进程号是7280,可输入命令行:jstack 7280 >7280.log


或者:输入命令行:jstack -F 7280 >test.log

方法5

1、进入jdk/bin,执行jvisualvm.exe

2、找到对应的线程号,然后进入线程 --> 线程 dump

方法6

Lunix下通过ps ef|grep java获取线程号,再通过kill -3 pid获取线程信息

怎么分析线程信息

在线程文件中查找smartbi字样, 查看完整的线程信息分析
线程的状态有BLOCK,WAITING,RUNNABLE
BLOCK是等待锁的线程,需要看该线程等待的线程在执行什么操作,如果持有锁的线程处于RUNNABLE则是正常行为(某些情况长时间RUNNABLE也是不正常行为,如执行一个简单sql数据库没有响应),如果处于BLOCk,要继续查询下个锁的进程, 通常就是两种结果RUNNABLE和死锁。
Waiting是等待别人唤醒的线程,代码里主动调用了wait() 引起的, 需要notify()唤醒,在smartbi产品的场景里,主要有池、电子表格报表执行, 比如,数据库连接池满了,新的获取数据库链接的线程会长时间处于waiting状态,直到现有使用连接池的数据库链接关闭,会唤醒其中的waiting线程继续执行,当线程长时间处于waiting状态,可能是需要重点关注分析的(见下文)。
RUNNABLE是正在执行的线程。
有时全部线程都处于RUNNABL状态,需要多次打印比较线程的执行状态, 如果通过这多次打印结果看到某个线程一直执行同一操作,如一直读取socket,一直在删除文件。
一般拿到线程信息,优先关注smartbi的block线程,block线程没问题时,这时通常一个个看,主要是看每个线程在干什么,通过这个干什么判断一些问题,这时候考验对产品的熟悉度。下面是常见的案例:

1.线程等待

通常lock是synchronized产生的,我们需要查找处于block状态的线程,

搜索locked <0x00000000eacb6600>(这个代表持有这个锁)
找到对应的持有锁线程,查看其执行逻辑(这时候靠人为判断逻辑有没有问题)
"http-bio-8072-exec-9" daemon prio=6 tid=0x0000000010e37800 nid=0x238c waiting on condition [0x000000001485c000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)

  • parking to wait for <0x00000000ec01f3a8> (a java.util.concurrent.FutureTask$Sync)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:196)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1011)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1303)
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:227)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at smartbi.connectionpool.ConnectionPool$7.validateConnection(ConnectionPool.java:662)
    at org.apache.commons.dbcp.PoolableConnectionFactory.validateObject(PoolableConnectionFactory.java:308)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:855)
  • locked <0x00000000ca80cae0> (a smartbi.connectionpool.ConnectionPool$5)
    at smartbi.connectionpool.ConnectionPool$5.borrowObject(ConnectionPool.java:504)
    at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:175)
    at smartbi.connectionpool.ConnectionPool.driverConnect(ConnectionPool.java:216)
    at smartbi.connectionpool.ConnectionPool.getConnection(ConnectionPool.java:354)
    at smartbi.freequery.querydata.store.DBSQLResultStore.executeInDatabase(DBSQLResultStore.java:1343)
  • locked <0x00000000ebffd8b0> (a smartbi.freequery.querydata.store.DBSQLResultStore)
    at smartbi.freequery.querydata.store.DBSQLResultStore.ensureGridDataInMemDB(DBSQLResultStore.java:4422)
    at smartbi.freequery.querydata.store.DBSQLResultStore.getGridDataInternal(DBSQLResultStore.java:3825)
    at smartbi.freequery.querydata.store.SQLResultStore.getGridData(SQLResultStore.java:156)
    at smartbi.freequery.report.SimpleReportBO.getGridDataInternal(SimpleReportBO.java:1005)
  • locked <0x00000000eacb6600> (a smartbi.freequery.report.SimpleReportBO)
    at smartbi.freequery.report.SimpleReportBO.getGridData(SimpleReportBO.java:981)
  • locked <0x00000000eacb6600> (a smartbi.freequery.report.SimpleReportBO)

    2.连接池满

    线程信息中出现大量在执行含GenericObjectPool.borrowObject的线程的(意味着好多操作在等待获取连接),代表连接池满了,具体的线程信息类似如下:
    "http-bio-8072-exec-41" daemon prio=6 tid=0x0000000010600000 nid=0x3588 in Object.wait() [0x0000000020f8d000]
    java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:485)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:810)
  • locked <0x00000000f93cdf60> (a smartbi.connectionpool.ConnectionPool$5)
    at smartbi.connectionpool.ConnectionPool$5.borrowObject(ConnectionPool.java:504)
    at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:175)
    at smartbi.connectionpool.ConnectionPool.driverConnect(ConnectionPool.java:216)
    at smartbi.connectionpool.ConnectionPool.getConnection(ConnectionPool.java:354)
    at smartbi.freequery.querydata.store.DBSQLResultStore.executeInDatabase(DBSQLResultStore.java:1343)
  • locked <0x00000000f4ae85e0> (a smartbi.freequery.querydata.store.DBSQLResultStore)
    at smartbi.freequery.querydata.store.DBSQLResultStore.ensureGridDataInMemDB(DBSQLResultStore.java:4422)
    at smartbi.freequery.querydata.store.DBSQLResultStore.getGridDataInternal(DBSQLResultStore.java:3825)
    at smartbi.freequery.querydata.store.SQLResultStore.getGridData(SQLResultStore.java:156)
    这时在监控界面看到连接池active的个数和数据源设置的大小是一样的。


    这时需要在系统一重启时,在"系统运维">"调试工具集">" 连接池信息"启动跟踪。
    连接数据到一半或以上时刷新页面分析获取数据库连接的代码来源。

    3.对象池满

    线程中出现如下内容时通常是对象池被使用满了
    at java.lang.Object.wait(Native Method)
  • waiting on <0x00000000c396d7b8> (a smartbi.pool.BusinessViewBOPool)
    at java.lang.Object.wait(Object.java:485)
    at smartbi.pool.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:839)
  • locked <0x00000000c396d7b8> (a smartbi.pool.BusinessViewBOPool)
    at smartbi.pool.BaseSmartbiObjectPool.borrowObject(BaseSmartbiObjectPool.java:148)
  • locked <0x00000000c396d7b8> (a smartbi.pool.BusinessViewBOPool)
    at smartbi.pool.BusinessViewBOPool.borrowObject(BusinessViewBOPool.java:47)
  • locked <0x00000000c396d7b8> (a smartbi.pool.BusinessViewBOPool)
    这时需要在系统一重启时,在"系统运维">"调试工具集">" 对象池信息"启动跟踪。
    对象池个数到一半或以上时刷新页面分析获取对象池的代码来源。

    4.死锁

    当线程出现相互等待时,就是代码出现死锁了
    "pool-2-thread-2":
    at smartbi.xxx(xxx.java:1)
  • waiting to lock <lockid1> (a smartbi.xxx)
    at smartbi.xxx(xxxxx.java:138)
  • locked < lockid2> (a smartbi.xxx)

    "pool-3-thread-3":
    at smartbi.xxx(xxx.java:999)
  • waiting to lock <lockid2> (a smartbi.xxx)
    at smartbi.xxx(xxxxx.java:234)
  • locked < lockid1> (a smartbi.xxx)
    这找到对应代码查看其synchronized对象是否一致。
    以下是可以产生死锁的代码
    Class A {
    Void a() {
    Synchronized(B.class) {
    Synchronized(C.class) {
    }
    }
    }
    Void b() {
    Synchronized(C.class) {
    Synchronized(B.class) {
    }
    }
    }
    }

    5.其他问题

    一一查看每个线程的具体执行逻辑内容,判断其正在处理的逻辑,这需要熟悉代码。


  • 无标签