Анализ исходного кода Dubbo --- распаковка и вставка

задняя часть исходный код Netty Dubbo

Анализ исходного кода Dubbo — распаковка и вставка


Про распаковку и вклейку

Что касается распаковки и приклеивания, на самом деле это явление, которое происходит, когда ссылка TCP отправляет данные.Эта статья не будет подробно объяснять, но в основном для того, чтобы увидеть, как dubbo справляется с этим явлением (dubbo не использует декодер в родной сети), и Он основан на собственном стеке протоколов для реализации собственныхENCODER/DECODER,

Если интересно, загляните сюдаНетти решает распаковку и приклеивание.

dubbo разборка/заклейка входа пакета

Вход находится в Дуббо.NettyCodecAdapter, который содержитencoderа такжеdecoderДля соответствующего определения, давайте посмотрим на соответствующие части распаковки.Давайте сначала посмотрим на первую часть:

com.alibaba.dubbo.remoting.buffer.ChannelBuffer message;
if (buffer.readable()) {
if (buffer instanceof DynamicChannelBuffer) {
buffer.writeBytes(input.toByteBuffer());
message = buffer;
} else {
int size = buffer.readableBytes() + input.readableBytes();
message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(
size > bufferSize ? size : bufferSize);
message.writeBytes(buffer, buffer.readableBytes());
message.writeBytes(input.toByteBuffer());
}
} else {
message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.wrappedBuffer(
input.toByteBuffer());
}

Сначала определите, есть ли в буфере данные для чтения, и если да, объедините сообщения, чтобы получить сообщение, а затем проанализируйте его.

Продолжайте смотреть на часть синтаксического анализа:

do {
saveReaderIndex = message.readerIndex();
try {
msg = codec.decode(channel, message);
} catch (IOException e) {
buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
throw e;
}
if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
message.readerIndex(saveReaderIndex);
break;
} else {
if (saveReaderIndex == message.readerIndex()) {
buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
throw new IOException("Decode without read data.");
}
if (msg != null) {
Channels.fireMessageReceived(ctx, msg, event.getRemoteAddress());
}
}
} while (message.readable());

Вы можете видеть, что это цикл, обрабатывающий сообщение до тех пор, пока оно не станет нечитаемым. Как видите, индекс считывателя сначала сохраняется для отката, а затем вводитсяdecoder, вотDubboCountCodec, обратите внимание здесь:DubboCountCodecТолько один полный стек протоколов dubbo (илиNEED_MORE_INPUT):

int save = buffer.readerIndex();
MultiMessage result = MultiMessage.create();
do {
Object obj = codec.decode(channel, buffer);
if (Codec2.DecodeResult.NEED_MORE_INPUT == obj) {
buffer.readerIndex(save);
break;
} else {
result.addMessage(obj);
logMessageLength(obj, buffer.readerIndex() - save);
save = buffer.readerIndex();
}
} while (true);
if (result.isEmpty()) {
return Codec2.DecodeResult.NEED_MORE_INPUT;
}
if (result.size() == 1) {
return result.get(0);
}
return result;

Вот текущийbufferИндекс чтения также для последующего отката (откат здесь не во внешнем слоеbuffer, чтобы различать здесь). можно увидеть, когдаdecodeто, что возвращаетсяNEED_MORE_INPUTозначает текущийbufferНедостаточно данных в середине, и стек протоколов dubbo не может быть полностью разобран.bufferИндекс чтения откатывается к ранее подготовленному индексу и выходит из цикла, возвращая результат.

Продолжайте смотреть здесьcodec.decode, и, наконец, находитExchangeCodecизdecodeMedium, или сегментированный, мы его сначала проигнорировали, это даббо параtelnetслужба поддержки:

// check length.
if (readable < HEADER_LENGTH) {
return DecodeResult.NEED_MORE_INPUT;
}

// get data length.
int len = Bytes.bytes2int(header, 12);
checkPayload(channel, len);

int tt = len + HEADER_LENGTH;
if (readable < tt) {
return DecodeResult.NEED_MORE_INPUT;
}

Здесь есть два случая:

  1. Читаемая длина меньше длины заголовка протокола, что указывает: читаемого поля недостаточно для объема данных заголовка протокола, возвратDecodeResult.NEED_MORE_INPUT.
  2. Текущий буфер содержит полный заголовок сообщения, получает длину полезной нагрузки, находит ее читаемую длину и не содержит данных всего стека протоколов, возвращаетDecodeResult.NEED_MORE_INPUT.
  3. В противном случае, это означает, что включен хотя бы один стек протоколов, затем происходит парсинг данных dubbo, конечно, после чтения могут остаться данные.

Вернемся ко второму фрагменту кода, если msgNEED_MORE_INPUT, затем поставьтеreaderIndexоткат. Конец цикла:

if (message.readable()) {
message.discardReadBytes();
buffer = message;
} else {
buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
}
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());

Если оно доступно для чтения, отбрасываем прочитанные байты, а затем кешируем оставшуюся информацию сообщения в буфере для следующего чтения.Пока что мы знаем, зачем dubbo нужно реализовывать собственную распаковку и залипание:
Dubbo需要解析自己独有的协议栈,而默认的方式不符合dubbo的解析方式.

# Распаковка и вклейка Анализ исходного кода Dubbo --- DIRECTORY и ROUTER