Netty: как мне отправить protobuf через HTTP без создания копий данных?

#java #netty

#java #netty

Вопрос:

Я пишу HTTP-клиент Netty для отправки данных protobuf на HTTP-сервер Netty через балансировщик нагрузки Haproxy.

Я пытался использовать HttpPostRequestEncoder для добавления атрибута body, но меня беспокоит создание нескольких копий данных, поскольку мне нужно преобразовать Protobuf в строку с обеих сторон.

Возможно ли отправлять двоичные данные напрямую (с указанием типа содержимого) с использованием HTTP? Объем данных является переменным.

Это мой клиентский конвейер —

     @Override
    protected ChannelHandler addDecoder() {
        return null;
    }

    @Override
    protected ChannelHandler addEncoder() {
        return new HttpClientCodec();
    }

    @Override
    protected ChannelHandler addMessageHandler() {
        return new HttpResponseHandler();
    }

    @Override
    protected PipelineSslContext addSslContext() {
        return null;
    }

    @Override
    protected List<ChannelHandler> addSecondaryDecoders() {
        return null;
    }

    @Override
    protected List<ChannelHandler> addSecondaryEncoders() {
        List<ChannelHandler> encoders = new ArrayList<>();
        encoders.add(new ChunkedWriteHandler());
        return encoders;
    }
 

И вот как я отправляю данные —

     //Message is a proto message. Ideally this could have been done with a custom ProtoToHttpRequest encoder 
    //but it doesn't seem to work.
    // This is also doing a data copy
    String data = Base64.encodeBase64String(message.toByteArray());
    //String data = new String(message.toByteArray());

    HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, httpUri);
    if (headerField != null) {
        Object value = message.getField(headerField);
        if (value != null) {
            request.headers().set(HttpHeaders.Names.COOKIE, ClientCookieEncoder.encode(
                    new DefaultCookie("SESSIONID", (String) value)));
        }
    }

    request.headers().set(HttpHeaders.Names.HOST, m_endPoint.getHost());
    request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
    HttpPostRequestEncoder bodyRequestEncoder = new HttpPostRequestEncoder(factory, request, false);
    bodyRequestEncoder.addBodyAttribute("message", data);
    request = bodyRequestEncoder.finalizeRequest();
    socket.write(request);
    if (bodyRequestEncoder.isChunked()) {
        socket.writeAndFlush(bodyRequestEncoder);
    }
    else
        socket.flush();