java 我是否必须根据netty中有效负载的大小来设置缓冲区大小?

wko9yo5t  于 2023-02-21  发布在  Java
关注(0)|答案(2)|浏览(140)

我阅读了netty.io的netty 4.1教程和GitHub中的对象回显示例,但它们没有详细说明发送大小不同的对象时缓冲区大小的问题。
假设我想发送一个包含一个int[]和一个float[]的对象,它是一个DTO,所以只有构造函数和getter。
我如何决定缓冲区的大小?我似乎找不到任何答案,所以我认为这是一个愚蠢的问题。但谷歌为什么要了解我在这方面的进展呢?总体来说,我对网络相当陌生。
我知道我需要在各自的通道管道中添加decoder和encoderHandlers,但我不知道如何在对象中实现不同大小的decoder和encoderHandlers。我知道ObjectDecoder和ObjectEncoder类,但我不知道应该将缓冲区设置为多大,因为DTO中的数组是动态创建的。

yruzcnhs

yruzcnhs1#

序列化数组的通常方法是,首先记录数组的长度,然后逐个序列化元素,我不确定你是否想问这个问题,希望能有所帮助

package com.ljy.netty.codec;

import java.util.Arrays;

/**
 * Using big-endian byte ordering, reference to the Bits class of the java library
 */
public class IntArrayCodecExample {

    public static byte[] encode(int[] ia) {
        byte[] bytes = new byte[ia.length * 4 + 4];
        writeInt(bytes, 0, ia.length);
        for (int i = 0; i < ia.length; i++) {
            writeInt(bytes, (i + 1) * 4, ia[i]);
        }

        return bytes;
    }

    public static int[] decode(byte[] bytes) {
        int length = readInt(bytes, 0);
        int[] ia = new int[length];
        int offset = 4;
        while(offset < bytes.length) {
            ia[offset / 4 - 1] = readInt(bytes, offset);
            offset += 4;
        }

        return ia;
    }

    private static void writeInt(byte[] bytes, int offset, int val) {
        bytes[offset + 3] = (byte) (val       );
        bytes[offset + 2] = (byte) (val >>>  8);
        bytes[offset + 1] = (byte) (val >>> 16);
        bytes[offset    ] = (byte) (val >>> 24);
    }

    private static int readInt(byte[] b, int off) {
        return ((b[off + 3] & 0xFF)      ) +
                ((b[off + 2] & 0xFF) <<  8) +
                ((b[off + 1] & 0xFF) << 16) +
                ((b[off    ]       ) << 24);
    }


    public static void main(String[] args) {
        int[] ia = new int[]{1, 3, 2, 4, 5};
        System.out.println(Arrays.toString(decode(encode(ia))));
    }
}
tv6aics1

tv6aics12#

如果你使用相对较小的对象,并且有足够的内存通过简单的序列化(dto, allocator) -> ByteBuf来处理所有请求,那么就享受这种简单性吧:

val size = calculateSerializedSize(dto)
val buf = ctx.alloc().buffer(size)
serialize(dto, buf)
ctx.write(buf)

但是如果你要处理大的甚至是巨大的对象,那么你需要考虑使用io.netty.handler.stream.ChunkedInput<ByteBuf>。例如,看看io.netty.handler.stream.ChunkedFile是如何处理巨大文件的:

pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new YourHandler());

...

// YourHandler
ctx.write(new YourCustomDtoChunkedInput(dto, ctx.alloc()))

相关问题