编解码技术

发布时间:2019-08-06 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了编解码技术脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

基于 Java 提供的对象输入/输出流 ObjectInputStreamObjectOutputStream, 可以直接把 Java 对象作为可存储的字节数组写入文件, 也可以传输到网络上.

Java 序列化的目的主要有两个:

  • 网络传输
  • 对象持久化

当进行远程跨进程服务调用时, 需要把被传输的 Java 对象编码为字节数组或者 ByteBuffer 对象. 而当远程服务读取到 ByteBuffer 对象或字节数组时, 需要将其解码为发送时的 Java 对象. 这被称为 Java 对象编解码技.

Java 序列化缺点

Java 序列化仅仅是 Java 编解码技术的一种, 由于它的种种缺陷, 衍生除了多种解码器技术和框架.

无法跨语言

对于跨进程的服务调用, 服务提供者可能会使用 C++ 或其他语言开发, 当我们需要和其他语言交互时, 由于 Java 序列化技术是 Java 语言内部的私有协议, 其他语言并不支持, 所以无法对其进行反序列化.

序列化后的码流太大

下面我们通过一个实例看下 Java 序列化后的字节数组大小.

public class UserInfo implements Serializable {

    PRivate static final long serialVersionUID = 1L;

    private String userName;
    private int userID;

    public byte[] codeC() {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        byte[] value = this.userName.getBytes();
        buffer.put(value);
        buffer.putInt(this.userID);
        buffer.flip();
        value = null;
        byte[] result = new byte[buffer.remaining()];
        buffer.get(result);
        return result;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getUserID() {
        return userID;
    }

    public void setUserID(int userID) {
        this.userID = userID;
    }
}
public class App 
{
    public static void main( String[] args ) throws Exception {

        UserInfo userInfo = new UserInfo();
        userInfo.setUserID(100);
        userInfo.setUserName("Welcome to Netty");

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.wrITeObject(userInfo);
        objectOutputStream.flush();
        objectOutputStream.close();

        byte[] bytes = byteArrayOutputStream.toByteArray();

        System.out.println("The jdk serializable length is: " + bytes.length);
        System.out.println("The byte array serializable length is: " + userInfo.codeC().length);
    }
}

测试结果

The jdk serializable length is: 102
The byte array serializable length is: 20

测试结果令人震惊, 采用 JDK 序列化机制编码后的二进制数组大小尽然是二进制编码的 5.1 倍. 在同等情况下, 编码后的字节数组越大, 存储的时候就越占空间, 存储的硬件成本就越高, 并且在网络传输时更占带宽, 导致系统的吞吐量降低.

序列化性能太低

可以让创建代码循环 100 万次, 然后在前后加入获取系统时间.

业界主流的编解码框架

GOOGLE 的 Protobuf 介绍

Protobuf 全称 Google Protocole Buffers, 它由谷歌而来, 在谷歌内部久经考验. 它将数据结构以 .proto 文件进行描述, 通过代码生成工具可以生成对应数据结构的 POJO 对象和 Protobuf 相关的属性和方法.

它的特点如下.

  • 结构化数据存储格式(XML JSON等);
  • 高效的编解码性能;
  • 语言无关、平台无关、扩展性好;
  • 官方支持 Java、C++ 和 Python 三种语言.

为什么不使用 xML. 尽管 xml 的可读性和可扩展性非常好, 也非常适合描述数据结构, 但是 xml 解析的时间开销和 xml 为了可读性而牺牲的空间开销都非常大, 因此不适合做高性能的通信协议. Protobuf 使用二进制编码, 在空间和性能上具有更大的优势.

Protobuf 另一个比较吸引人的地方就是它的 数据描述文件和代码生成机制, 利用数据描述文件对数据结构进行说明的优点如下.

  • 文本化的数据结构描述语言, 可以实现语言和平台无关, 特别适合异构系统间的集成.
  • 通过标识字段的顺序, 可以实现协议的前向兼容;
  • 自动代码生成, 不需要手工编写同样数据结构的 C++ 和 Java 版本;
  • 方便后续的管理和维护. 相比于代码, 结构化的文档更容易管理和维护.

总结

我们判断一个编码器框架的优劣时, 往往会考虑以下几个因素.

  • 是否支持跨语言, 支持的语言种类是否丰富;
  • 编码后的码流大小;
  • 编解码的性能;
  • 类库是否小巧, API 使用是否方便;
  • 使用者需要手工开发的工作量和难度.

脚本宝典总结

以上是脚本宝典为你收集整理的编解码技术全部内容,希望文章能够帮你解决编解码技术所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。