dubbo服务中的hessian序列化工厂使用hashmap加锁在高并发场景下的问题

bloghongxiorg 2016-11-10

[摘要:1.题目描绘我们正在对5个dubbo接心并收举行测试,统共线程数是64个,一直的挪用那些接心。视察到的非常浮现是TPS动摇较大,时下时低。我们视察线程的运转状态是如许]

1.问题描述

我们在对5个dubbo接口并发进行测试,总共线程数是64个,不停的调用这些接口。观察到的异常显现是TPS波动较大,时高时低。

我们观察线程的运行状况是这样的:

上图红色部分是线程阻塞的情况。

我们查看线程栈的信息发现有20多个用户线程处于Blocked状态,blocked状态的代码如下:

"DubboServerHandler-192.168.183.17:20880-thread-200"daemonprio=10tid=0x00007fc0e802b800nid=0x6a8fwaitingformonitorentry[0x00007fbf25bda000]

java.lang.Thread.State:BLOCKED(onobjectmonitor)

atcom.jd.com.caucho.hessian.io.SerializerFactory.getSerializer(SerializerFactory.java:164)

-locked<0x00000000c35af008>(ajava.util.HashMap)

atcom.alibaba.com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:406)

atcom.alibaba.com.caucho.hessian.io.CollectionSerializer.writeObject(CollectionSerializer.java:102)

atcom.alibaba.com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:408)

atcom.alibaba.com.caucho.hessian.io.JavaSerializer$FieldSerializer.serialize(JavaSerializer.java:313)

这说明如果该服务在该并发下还是会出现用户线程阻塞在代码

atcom.alibaba.com.caucho.hessian.io.SerializerFactory.getSerializer(SerializerFactory.java:164)处的情况,对于服务的稳定性和TPS都会造成一定的影响。

2.问题分析

根据上述日志的分析,我们定位到了线程锁部分的代码,我们打开该代码如下所示:

if(_cachedSerializerMap!=null){

synchronized(_cachedSerializerMap){

serializer=(Serializer)_cachedSerializerMap.get(cl);

}

可以看到此处使用了HashMap,在并发读写map的代码的地方都添加了synchronized关键字。而本问题也就是在该处BLOCKED了。如果并发较大的时候,线程释放锁的速度赶不上线程争夺资源的速度就会导致用户线程的锁定。

3.优化方案

在高并发的场景下,Hashmap+synchronized的锁的粒度太大,直接锁定了整个HashMap对象,那么我们可以用ConcurrentHashMap来降低锁的粒度,这样并发处理能力就能够增强。

我在搜索类SerializerFactory的时候,也正好搜索到了hessian-4.0.7.jar中也有这个类,应该是dubbo从hessian里移植过来的另一个类。在这个版本里它就将HashMap替换为ConcurrentHashMap,

它替换之后的代码是这样的:

privateConcurrentHashMap_cachedSerializerMap;

privateConcurrentHashMap_cachedDeserializerMap;

Serializerserializer;

if(_cachedSerializerMap!=null){

serializer=(Serializer)_cachedSerializerMap.get(cl);

if(serializer!=null)

returnserializer;

}

它的区别就是使用ConcurrentHashMap,去除了synchronized关键字。

接下来我们也做这样的修改,替换jar包之后,再对服务进行一次压测,结果如下:

1.线程中无Blocked状态的用户线程。

2.TPS更加稳定。

TPS变得更加稳定,没有较大的波动。

从测试来看这种优化之后是有实际效果的,dubbo服务的并发能力明显增强了许多。

总结:

对于并发较高的dubbo服务,若希望提高并发处理能力,则应该做这样的优化。

摘自:http://www.ithao123.cn/content-8941250.html

相关推荐