iohao / ioGame

无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你可以很容易的搭建出一个集群无中心节点、集群自动化、分布式的网络服务器;FXGL、Unity、UE、Cocos Creator、Godot、Netty、Protobuf、webSocket、tcp、socket;java Netty 游戏服务器框架;
http://game.iohao.com
GNU Affero General Public License v3.0
880 stars 190 forks source link

建议未来支持高性能序列化框架-flatbuffers和simple-binary-encoding #317

Open cnrainbing opened 3 months ago

cnrainbing commented 3 months ago

新增功能的使用场景

描述功能的使用场景、作用;或描述功能所带来的好处 金融业务场景:海量挂载、高性能低延迟推送

他们两个的易用性也是非常高、性能也非常好

  1. https://github.com/real-logic/simple-binary-encoding
  2. https://github.com/google/flatbuffers
iohao commented 3 months ago

框架未来计划支持 https://github.com/apache/fury

框架内置支持的序列化框架的前提条件是:使用需要足够简单。而简单的定义也只有一条,即支持 java 代码定义协议。因为这样可以减少一个编译的步骤(即,通过 xx 协议文件生成 java 代码)。

这是因为,服务器通常是服务的提供方,而编写协议自然是由服务器开发者提供。如果需要先写 DSL 后,在将 DSL 文件编译成 java 代码后才能使用的,那么可以确定这是一件无聊的事情;而通过 java 定义的协议文件则更加直观。如下

@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Student {
    /** name */
    String name;
}

Student 类使用的是 java 代码定义的协议,有如下优势

  1. 即使是 java 新手也能看得明白,而通过 DSL 生成的 java 代码,是不可能这么清晰的。
  2. 同时,Student 类既能支持 protobuf ,又能支持 json ,且开发者无需做任何变更;这点是 DSL 做不到的。
  3. 还能支持 JSR380 验证 (yuque.com),在属性上添加 JSR380 相关注解即可;这点是 DSL 做不到的。
  4. 此外,还能在协议类中添加一些自定义方法,这点是 DSL 做不到的。
  5. 减少学习成本,不需要学习各种 DSL 相关库的语法;

结论,支持 java 代码定义协议的序列化库,会优先做支持。比如,将来支持了 Fury,那么开发者无需变更现有的业务代码,就能直接使用。从而为开发者减少迁移成本、维护成本、学习成本。

cnrainbing commented 3 months ago

好的,期待ioGame支持国产Fury

iohao commented 3 months ago

相关文档 pb、json、扩展协议 (yuque.com)

示例:不对现有的业务代码做变更,只需设置当前所使用的编解码器就能切换序列化库。

public void chooseCodec() {
    // 使用 JSON 编解码
    IoGameGlobalSetting.setDataCodec(new JsonDataCodec());
    // 使用 Protobuf 编解码
    IoGameGlobalSetting.setDataCodec(new ProtoDataCodec());
    // 使用 Fury 编解码
    IoGameGlobalSetting.setDataCodec(new FuryDataCodec());
}   

之后,如果支持了 Fury,我们只需要扩展一个 FuryDataCodec 编解码器即可。

这种扩展方式基本做到了:零迁移成本、零维护成本、零学习成本。

cnrainbing commented 3 months ago

看起来非常灵活,我可以实现 DataCodec 这个接口类自定义自己的编解码协议吧,比如我自定义simple-binary-encoding协议可以吧?

/**
 * 业务数据的编解码器
 *
 * @author 渔民小镇
 * @date 2022-05-18
 */
public interface DataCodec {
    /**
     * 将数据对象编码成字节数组
     *
     * @param data 数据对象
     * @return bytes
     */
    byte[] encode(Object data);

    /**
     * 将字节数组解码成对象
     *
     * @param data      数据对象的字节
     * @param dataClass 数据对象 class
     * @param <T>       t
     * @return 业务参数
     */
    <T> T decode(byte[] data, Class<?> dataClass);

    /**
     * 编解码名
     *
     * @return 编解码名
     */
    default String codecName() {
        return this.getClass().getSimpleName();
    }
}
iohao commented 3 months ago

是的