针对不同的性能问题,如何分析瓶颈?
首先,检查压力机端是否存在瓶颈,需要监控压力机CPU、内存、磁盘IO、网络IO等资源是否有满载的情况。单台压力机不建议设置过高的并发数,同时尽量减少不必要的关联和检查点,减少损耗。如果被测应用接入了APM探针,可以查看压力机端统计到的事务响应时间与APM工具统计到的服务端处理耗时的差异,若事务响应时间明显大于服务端耗时,也说明压力机端存在瓶颈。其次,检查是否为服务端瓶颈。如果确实是服务端处理耗时长,那么建议借助APM工具进行链路分析,在交易链路上的耗时增长趋势会指引我们找到最终的瓶颈点。
例如一笔交易依次经过A、B、C这3个服务节点,如果A和C的内部处理耗时较短,而B服务节点的内部处理耗时较长,那就说明B服务节点以及它所关联的中间件、数据库等资源可能存在瓶颈。
如果是,瓶颈通常表现在数据库连接池和慢SQL上。对于未使用连接池的情况,服务直接通过JDBC与数据库交互,这种情况下应用服务器端不会有连接池耗尽的问题,但数据库服务器端是有总连接数限制的,以MySQL为例,它可以通过max_connections设置最大连接数。如果数据库服务器端总连接数耗尽,在客户端就会表现出获取连接耗时长的现象。新建和销毁数据库连接是个昂贵的操作,为了优化系统运行效率,应该降低频繁建立连接的系统开销,建议使用连接池技术。对于使用连接池的情况,以Druid组件为例进行阐述。Druid是阿里巴巴开源的数据库连接池,作为后起之秀,性能比DBCP、c3p0更高,使用也越来越广泛。Druid组件会为应用端所要访问的每个数据库维护一个连接池,当应用需要访问数据库时,需要先从连接池内借用一个连接,执行完SQL,得到响应结果后,将连接归还给连接池。
连接池的相关参数主要有initialSize、minIdle和maxActive。其中initialSize表示初始化时建立物理连接的个数,初始化发生在调用init方法或者第一次调用getConnection方法时;minIdle表示最小连接池数量,Druid会定时扫描连接池的连接,如果空闲连接数大于该值,则关闭多余的连接,反之则创建更多的连接以满足最小连接池数量的要求;maxActive表示最大连接池数量。当连接池内所有连接都处于繁忙状态时,如果有新的访问数据库的操作,就会表现出获取连接耗时较长的现象。导致连接池内连接耗尽的常见原因有如下几种。
1)慢SQL长时间占用连接。此时需通过APM工具或数据库服务器端的监控来排查是否有慢SQL
2)业务逻辑中有频繁访问数据库的情况。例如在循环内部访问数据库的逻辑,如果循环次数很多,那么访问数据库的频率就会非常高,而每一次交互都会有取连接和归还连接的消耗,很容易导致连接不够用,应尽量改造成批量查询来缓解连接池的压力。
3)连接池设置过小。例如Druid默认最大连接数是8,如果一个应用与数据库交互较为频繁,可以将连接池适当调大。不过需要注意,