jemter压测dubbo服务遇到的瓶颈分析

dubbo微服务分为服务提供者和服务消费者,单个linux虚拟机上部署单个dubbo服务节点,机器配置一般是4核8G内存,JVM参数配置是最大JVM内存是4G,其他的参数配置请百度参考。这次小编我用的是8核8G内存的linux虚拟机,该机器上部署了2个微服务节点,JVM最大内存是2G。我把服务消费者部署在另外的linux虚拟机上,部署了两个服务消费者,然后用nginx作负载均衡,请求分别路由到这两个服务消费者上,服务消费者获取dubbo服务消费,这种RPC性能比HTTP请求高效,DUBBO协议是属于二进制序列化,HTTP是文本协议,有很多无用请求头,性能没DUBBO好,但是可以忽略这块影响。把业务逻辑全写在dubbo服务提供者,主要是插入数据库表信息、查询数据库表校验信息、更新数据库表信息、删除数据库表信息,事务控制是采用spring声明式事务@Transactional(rollbackFor=Exception.class) ,当程序抛出异常或主动抛出runtimeException时,事务就会回滚。这个过程中,加了一些业务判断,如果判断不符合业务逻辑就主动抛异常,让事务回滚,数据库不会有脏数据,强制保证了数据库的ACID原则。大概操作十几张表,正常情况下的mysql数据库,cpu和内存都良好,大概三秒钟完成整个服务消费。程序正常运行,但是压测的时候,jemter配置40线程的情况下,并发上来了就爆出了各种问题。下面我列举一下。

问题1、dubbo服务消费者与服务提供者的连接超时了,报错信息的部分内容是cause: Waiting server-side response timeout by scan timer. start time: 2019-06-21 14:48:39.870, end time: 2019-06-21 14:49:04.900, 
 client elapsed: 0 ms, server elapsed: 25030 ms, timeout: 25000 ms, request: Request [id=781517, version=2.0.0,
 twoway=true, event=false, broken=false, data=RpcInvocation,服务消费者设置了连接超时时间为25秒,由于服务提供者执行时间超过了25s还没有返回信息,就断开了连接,报超时错误。原因是数据库压力上来了,SQL语句执行会慢下来,超过了25秒,那么服务提供者没有返回信息给消费者。这个时候有可能造成数据不一致,比如服务消费者有自己独立的数据库,会根据服务提供者返回的信息记录数据,因为服务提供者没有正常返回,服务消费者捕捉到异常,就记录异常数据,其实服务提供者执行会有一部分是最终正常的,服务提供者对应操作的数据库也是正常的业务数据,也就是说这个时候出现了分布式微服务的不同数据库的数据非一致性的问题。解决跨数据库数据一致性的方法一般是两种:补偿或回退。绝大多数公司都是采用补偿模式。目前服务消费者是没有作补偿的机制,所以压测的时候就很尴尬了,数据一致对不上,服务消费者需要改造逻辑,当发生超时异常的时候,记录数据,后面再rpc调服务提供者查询到正常数据的时候,把服务消费者的数据库表的异常状态改回正常,这样就是以服务提供者的数据库表为准的前提下,补偿其他的。最终保证一致性。

问题2、数据库druid连接池的最大连接数不够用,一开始配置了50个,后来发现不够用,小编我改成了100个,但是发现还报同样的错误。其实druid开多少个连接池的最大连接数是看mysql的配置的,你配得大一些,mysql的配置跟不上,它们建立了连接,但是执行SQL语句特别慢,java线程执行很快,一下子又把100个连接占满了,又报同样的错误。小编不是很清楚服务器配置,应该是八核八线程,也就是说并行8个线程在运算。jemter的40线程发到服务消费者的服务器上,分别是20个线程,一台8核8线程的机器上处理20个线程,并发处理的时间是很短的,假设服务消费者在1秒内可以处理20*4,而服务提供者在一秒钟内只能处理20*4,mysql一秒内只能处理20,但是mysql执行时间特别慢,是服务提供者的n倍,mysql服务端很慢才返回给服务提供者,导致了快进慢出,不断有请求进来,迟迟没有返回。原来一秒返回,现在需要n秒。压力在mysql服务端。

问题3、数据库锁超时,由于开启了事务,操作某个表的某行时就锁了这行,锁的时间配置短,超时了,其他sql还没执行完,这个时候程序尝试重新提交事务,但是就报错了。解决办法把数据库锁的时间加长。org.springframework.dao.CannotAcquireLockException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve com.crt.loan.appl.common.service.mapper.LcApplMtdMapper.deleteLcApplMtdDtlByApplSeq-Inline

问题4、java io、jvm垃圾回收卡顿。 这个涉及JVM调优,需要不断修改JVM参数配置。如果是部署在tomcat的项目可以用JDK 自带的 jconsole.exe工具连接上服务端,观察线程、堆栈内存大小。dubbo应用的,不知道怎么观察。按我的做法是把JVM的最大内存改成4G,其他JVM参数也跟着调整。linux内核也跟着调优。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值