dubbo是一个分布式服务框架,在国内比较常用,在开发过程中遇到一个浮点数反序列化问题。
问题描述,当参数是float类型的3.7,反序列化却得到了一个double类型的值:3.700000047683716。
然后,我写了个测试程序:
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import com.alibaba.com.caucho.hessian.io.Hessian2Input; import com.alibaba.com.caucho.hessian.io.Hessian2Output; public class TestHessionLite { public static void main(String[] args) throws IOException { HashMap<String,Float> map=new HashMap<String,Float>(); Float loat=new Float(3.7); map.put("3.7", loat); byte[] aa=TestHessionLite.serialize(map); Object mm=TestHessionLite.deserialize(aa); System.out.println(mm.toString()); } public static byte[] serialize(Object obj) throws IOException{ ByteArrayOutputStream os = new ByteArrayOutputStream(); Hessian2Output ho = new Hessian2Output(os); byte[] cc = null; try { if(obj==null) throw new NullPointerException(); ho.writeObject(obj); ho.flushBuffer(); cc=os.toByteArray(); } catch (Exception e) { e.printStackTrace(); }finally{ ho.close(); } return cc; } public static Object deserialize(byte[] by) throws IOException{ try { if(by==null) throw new NullPointerException(); ByteArrayInputStream is = new ByteArrayInputStream(by); Hessian2Input hi = new Hessian2Input(is); return hi.readObject(); } catch (Exception e) { e.printStackTrace(); } return null; } }
输出结果为
{3.7=3.700000047683716}
然后由分别使用3.5、3.6进行测试
{3.6=3.5999999046325684} {3.5=3.5}
经过测试,并不是所有小数都有问题,部分小数会出现序列化问题。
我的dubbo服务序列化使用的是dubbo默认的hession2,而使用hessian2协议,也就是传输对象序列化,它是二进制的RPC协议。
经过分析,问题应该是出在了十进制浮点数转二进制。
后面又查看了相关资料,以及写了十进制和二进制互转的测试程序发现,就是不分小数在float单精度下是无法表示出来的。具体原因可以见下面资料http://blog.csdn.net/zcczcw/article/details/7362473。
如果将float,改成double,就不存在刚才精度问题了,因为double是双精度,可以保存64位二进制;
但是当小数点超过8位时,double也会被截取。
而是用kryo进行序列化则不会出现上面问题,因为kryo不是通过二进制存储,是通过字节数组来进行存储,这样可以保证数据不用进行转化。
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import org.apache.commons.codec.binary.Base64; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.JavaSerializer; public class TestKryo { public static void main(String[] args) { HashMap<String,Float> map=new HashMap<String,Float>(); Float loat=new Float(3.7); map.put("value", loat); String aa=TestKryo.serialize(map); Object mm=TestKryo.deserialize(aa,HashMap.class); System.out.println(mm.toString()); } private static <T extends Serializable> String serialize(T obj) { Kryo kryo = new Kryo(); kryo.setReferences(false); kryo.register(obj.getClass(), new JavaSerializer()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Output output = new Output(baos); kryo.writeClassAndObject(output, obj); output.flush(); output.close(); byte[] b = baos.toByteArray(); try { baos.flush(); baos.close(); } catch (IOException e) { e.printStackTrace(); } return new String(new Base64().encode(b)); } @SuppressWarnings("unchecked") private static <T extends Serializable> T deserialize(String obj, Class<T> clazz) { Kryo kryo = new Kryo(); kryo.setReferences(false); kryo.register(clazz, new JavaSerializer()); ByteArrayInputStream bais = new ByteArrayInputStream( new Base64().decode(obj)); Input input = new Input(bais); return (T) kryo.readClassAndObject(input); } }
相关推荐
默认就是⾛ dubbo 协议,单⼀⻓连接,进⾏的是 NIO 异步通信,基于 hessian 作为序列化协议。使⽤的场景是:传输数据量⼩ (每次请求在 100kb 以内),但是并发量很⾼。 为了要⽀持⾼并发场景,⼀般是服务提供者就⼏...
Dubbo序列化协议5连问,你接得住不?
双重序列化-avro 适用于dubbo的avro序列化工具。1.从src编译我们使用maven来构建和管理依赖项。 下载src git clone https://github.com/dubbo/dubbo-serialization-avro.git 从src构建,然后安装到本地maven存储库。...
NULL 博文链接:https://yuhuiblog695685688425687986842568269.iteye.com/blog/2404523
dubbo自动化测试
a --args gadget入参,多个参数使用多次该命令传入,例-a -a Calc-p --protocol [dubbo|http] 通讯协议名称,默认缺省dubbo-s --serialization [hessian|java] 序列化类型,默认缺省hessian-t --target 目标,例:...
dubbo可视化工具
dubbo可视化管理工具
sacla编写的dubbo自动化部署工具,项目是eclipse编写的
引入 dubbo框架 需要引用dubbo标签,dubbo.xsd 可以解决标签不识别的问题
1.dubbo-zookeeper springSpringMVC 一个生产者,多消费者 例子 2. ssm-dubbo 源码 ssm-tomcat 里放的是 warbao ,程序包 zookeeper-3.4.9 zookeeper 免安装包 设置都是默认的 zookeeper 端口 2181 dubbo-...
这是Dubbo空指针问题测试代码,测试Dubbo 2.6.3版本使用XML配置/注解配置+check参数不同情况下,各个场景的异常报错。 建议配合博文使用。
内容概要:最新2023年Java dubbo后端面试题整理, 包含工作原理,序列化协议,序列化协议等等问题, 用简洁明了的语言,通俗易懂地阐述了dubbo相关面试的知识点。 适用人群:适合想了解或学习Spring的 IT 学生、开发...
自动用scala写的dubbo服务自动化部署工具,工程是eclipse编写的
dubbo服务是阿里所出的一个框架,结合zookeeper来实现透明化远程调用。
dubbo资源 dubbo-admin dubbo demo
解决dubbo启动报错,加载失败问题。
34_dubbo都支持哪些通信协议以及序列化协议?
Dubbo是阿里巴巴开源的分布式服务化...本教程以Dubbo为核心框架,基于真实的第三方支付项目系统架构实战经验而形成的一整套分布式服务化系统架构技术解决方案。是你学习和了解现今最流行的“微服务架构”的首选教程。