这一小节主要讨论两个问题,一是描述Datastax Cassandra Driver为请求和响应定义的的数据结构;二是在收发数据都经过了哪些编解码。
一、数据结构:
driver发送/接收数据的结构分为两种版本:V1和V2共用的版本和V3使用的版本(如下图):
(1)version, 不解释,V3还是V1/V2
(2)flags, 分两种,使用序列化方式压缩进数据帧内
(header.writeByte(Header.Flag.serialize(frame.header.flags));)
a) TRACING: Returns whether tracing is enabled for this query or not.
b) COMPRESSED 是否压缩
(3)stream :很关键,标示数据帧的id. 收发一致以保持数据的发送和接收以一个对应起来。
(4)opcode: 编解码方式,例如对于请求,Query类型的opcode是7,从而服务器在接收到Driver发送的请求后,根据7的Requests.Query.coder进行解码,因为明显不同类型的请求的编解码方式是不同的。
STARTUP (1, Requests.Startup.coder), CREDENTIALS (4, Requests.Credentials.coder), OPTIONS (5, Requests.Options.coder), QUERY (7, Requests.Query.coder), PREPARE (9, Requests.Prepare.coder), EXECUTE (10, Requests.Execute.coder), REGISTER (11, Requests.Register.coder), BATCH (13, Requests.Batch.coder), AUTH_RESPONSE (15, Requests.AuthResponse.coder);
(5) length: 数据帧Body内容的总长度;
(6)body: 例如对于仅有HashMap属性的Credentials请求类型:
body分为2部分:第一部分为:总的长度(值为下图中x,区别于5);第二部分:数据内容(如下)
总体代码如下:
header.writeByte(frame.header.version.toInt()); header.writeByte(Header.Flag.serialize(frame.header.flags)); writeStreamId(frame.header.streamId, header, protocolVersion); header.writeByte(frame.header.opcode); header.writeInt(frame.body.readableBytes()); return ChannelBuffers.wrappedBuffer(header, frame.body);
二、编解码Codec
了解完数据帧的编码后,我们来了解下netty对收发数据的编解码,首先可以从以下代码可以看出收发数据编解码的过程和顺序:
pipeline.addLast("frameDecoder", new Frame.Decoder()); pipeline.addLast("frameEncoder", frameEncoder); if (compressor != null) { pipeline.addLast("frameDecompressor", new Frame.Decompressor(compressor)); pipeline.addLast("frameCompressor", new Frame.Compressor(compressor)); } pipeline.addLast("messageDecoder", messageDecoder); pipeline.addLast("messageEncoder", messageEncoderFor(protocolVersion)); pipeline.addLast("dispatcher", connection.dispatcher);
根据netty对收发数据处理的流程(如下图)可知:
datastax的转化流程图如下:
其中Frame.Decoder()为LengthFieldBasedFrameDecoder;dispatcher为SimpleChannelUpstreamHandler,其他都为OneToOneDecoder
总结:Driver 对于数据帧的定义方式非常典型:有identify的标记位,有影响后面body处理的压缩等flag,有长度字段和编解码方式字段;同时编解码也挺齐全:有压缩,也有不同请求的封装。
从driver对netty的使用来看,netty确实是强大的网络程序构架框架,相比较自己去一步一步码nio的server/client程序要高效的多。