保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

基于Netty的高性能RPC框架Nifty协议传输层编解码全

  ThriftCodecManager与对象读取
  在编写服务端代码的时候,我们创建了ThriftCodecManager这个对象,该对象是用来管理编解码器ThriftCodeclt;?的,在初始化的时候会创建各种类型的编解码器放到缓存中,以供服务处理器ThrfitServiceProcessor使用。接下来我们就深入分析这个编解码器管理器。
  通常我们使用的就是默认变成ThriftCodec数组构造方法来创建该对象,内部持有guava提供的缓存privatefinalLoadingCacheThriftType,ThriftCodeclt;?typeCodecs;publicThriftCodecManager(ThriftCodeclt;?。。。codecs){this(newCompilerThriftCodecFactory(ThriftCodecManager。class。getClassLoader()),ImmutableSet。copyOf(codecs));}publicThriftCodecManager(ThriftCodecFactoryfactory,SetThriftCodeclt;?codecs){this(factory,newThriftCatalog(),codecs);}
  主要分三步来添加编解码器到缓存typeCodecs中,构造typeCodecs,根据ThriftType来动态构建编解码器添加到缓存中;使用的是guavacache,这个东西公司内部基础架构部门也用的不少,作为本地缓存提供了挺多的策略,非常推荐花半小时学习一下;添加支持基本类型的编解码器,比如StringThriftCodec,IntThriftCodec;将我们自己定义的编解码器也加入到缓存中;
  接下来按照顺序依次介绍1。1。读取集合类型参数typeCodecsCacheBuilder。newBuilder()。build(newCacheLoaderThriftType,ThriftCodeclt;?(){publicThriftCodeclt;?load(ThriftTypetype)throwsException{switch(type。getProtocolType()){caseSTRUCT:{returnfactory。generateThriftTypeCodec(ThriftCodecManager。this,type。getStructMetadata());}caseMAP:{ThriftCodeclt;?keyCodectypeCodecs。get(type。getKeyType());ThriftCodeclt;?valueCodectypeCodecs。get(type。getValueType());returnnewMapThriftCodec(type,keyCodec,valueCodec);}caseSET:{ThriftCodeclt;?elementCodectypeCodecs。get(type。getValueType());returnnewSetThriftCodec(type,elementCodec);}caseLIST:{ThriftCodeclt;?elementCodectypeCodecs。get(type。getValueType());returnnewListThriftCodec(type,elementCodec);}}}});
  比如ThriftTypeMAP,分别从缓存获取key和value的编解码器,从而来构建map的编解码器MapThriftCodec
  在这之前需要知道编解码器其实就是提供了read和write方法,从协议中读取和写出数据。publicinterfaceThriftCodecT{TheThrifttypethiscodecsupports。TheThrifttypecontainstheJavagenericTypeofthecodec。publicThriftTypegetType();ReadsavaluefromsuppliedThriftprotocolreader。paramprotocoltheprotocoltoreadfromreturnthevalue;notnullthrowsExceptionifanyproblemsoccurredwhenreadingorcoercingthevaluepublicTread(TProtocolprotocol)throwsException;WritesavaluetothesuppliedThriftprotocolwriter。paramvaluethevaluetowrite;notnullparamprotocoltheprotocoltowritetothrowsExceptionifanyproblemsoccurredwhenwritingorcoercingthevaluepublicvoidwrite(Tvalue,TProtocolprotocol)throwsException;}
  基本类型的编解码器在之前的博客中说过,这里就看下MapThriftCodec和基本类型的编解码器有什么不同。publicMapK,Vread(TProtocolprotocol)throwsException{returnnewTProtocolReader(protocol)。readMap(keyCodec,valueCodec);}
  继续往下看:TProtocolReader:publicK,VMapK,VreadMap(ThriftCodecKkeyCodec,ThriftCodecVvalueCodec)throwsException{TMaptMapprotocol。readMapBegin();MapK,VmapnewHashMap();for(inti0;itMap。size;i){KkeykeyCodec。read(protocol);VvaluevalueCodec。read(protocol);map。put(key,value);}protocol。readMapEnd();returnmap;}
  是不是很容易理解,拿到key和value的编解码器后,不停的往下读即可。
  比较疑问的地方就是这里没有涉及到循环遍历i,实际上这是关于map的协议来决定的,protocal。readMapBegin在TBinaryProtocal中的实现是,依次读取一个字节,一个字节,4个字节分别表示key的类型,value的类型和元素数量。得到了map中元素数量tMap。size后,由于每次读取key和value的时候buffer中的指针都会移动,读完了value后,能保证下次读到的就是下一个元素的key。最后将结果放到构建的hashMap中即可。1。2。读取结构体
  方法的形参里面除了基本类型,集合类型外,经常还能遇到结构体类型,对于java来说就是对象,这个时候对应的处理如下。caseSTRUCT:{returnfactory。generateThriftTypeCodec(ThriftCodecManager。this,type。getStructMetadata());}
  做点小改动,在这里使用一个新的ThriftCodecManager构造方法,传入编解码器工厂类ReflectionThriftCodecFactoryThriftCodecManagermanagernewThriftCodecManager(newReflectionThriftCodecFactory());
  其实还有个工厂类CompilerThriftCodecFactory,看名字是个自建编译器的工厂类,看过内部实现代码多而且不大好理解,所以这里使用反射方式的编解码器工厂类。
  ReflectionThriftCodecFactory继承自ThriftCodecFactory,提供了获取编解码器的方法。publicinterfaceThriftCodecFactory{ThriftCodeclt;?generateThriftTypeCodec(ThriftCodecManagercodecManager,ThriftStructMetadatametadata);}
  ReflectionThriftCodecFactory的实现如下:publicclassReflectionThriftCodecFactoryimplementsThriftCodecFactory{OverridepublicThriftCodeclt;?generateThriftTypeCodec(ThriftCodecManagercodecManager,ThriftStructMetadatametadata){switch(metadata。getMetadataType()){caseSTRUCT:returnnewReflectionThriftStructCodec(codecManager,metadata);caseUNION:returnnewReflectionThriftUnionCodec(codecManager,metadata);default:thrownewIllegalStateException(format(encounteredtypes,metadata。getMetadataType()));}}}
  那么问题就是,ThriftStructMetadata如何得到以及干嘛用的,看名字就知道这是保存结构体元数据的。由type。getStructMetadata()得到,那么问题就是如何构造的ThriftType。其实在最开始构造ThriftServiceProcessor的时候就构造好了,
  创建过程比较复杂,简单来说就是:构建ThriftServiceProcessor的时候,会将构建ThriftServiceMetadata;而构建ThriftServiceMetadata的时候会构建ThriftMethodMetadata;构建的时候会构建List;每个ThriftFieldMetadata都代表一个方法形参,内部持有一个ThriftType,到这里就知道了ThriftType是属于ThriftFieldMetadata,在构建ThriftMethodMetadata的时候会得到ThriftType,如何得到?其实就是根据方法形参得到ThriftType的,从目录类ThriftCatalog获取到,其内部存有一个Type和ThriftType的映射,来简单看下。
  ThriftCatalog:privatefinalConcurrentMapType,ThriftTypetypeCachenewConcurrentHashMap();publicThriftTypegetThriftType(TypejavaType)throwsIllegalArgumentException{ThriftTypethriftTypetypeCache。get(javaType);if(thriftTypenull){thriftTypegetThriftTypeUncached(javaType);typeCache。putIfAbsent(javaType,thriftType);}returnthriftType;}
  基于此,在构建ThriftMethodProcessor的时候,再跟进ThriftCodecManager就能得到MapShort,ThriftCodeclt;?ImmutableMap。BuilderShort,ThriftCodeclt;?builderImmutableMap。builder();for(ThriftFieldMetadatafieldMetadata:methodMetadata。getParameters()){builder。put(fieldMetadata。getId(),codecManager。getCodec(fieldMetadata。getThriftType()));}parameterCodecsbuilder。build();
  所以在处理接收到的数据的时候,可以根据fieldid来获取对应的编解码器了。
  知道ThriftType如何获得后,再回过头来看ReflectionThriftStructCodec如何解析结构体的。protectedfinalThriftStructMetadatametadata;protectedfinalSortedMapShort,ThriftCodeclt;?fields;OverridepublicTread(TProtocolprotocol)throwsException{TProtocolReaderreadernewTProtocolReader(protocol);MapShort,ObjectdatanewHashMap(metadata。getFields()。size());while(reader。nextField()){shortfieldIdreader。getFieldId();ThriftCodeclt;?codecfields。get(fieldId);Objectvaluereader。readField(codec);data。put(fieldId,value);}buildthestructreturnconstructStruct(data);}
  代码简化了很多,但是主体逻辑留了下来。从这部分代码可以看到,这和服务端读取数据的逻辑是一样的,具体的可以参考服务端读取数据。最后得到的data中key为struct(即java对象)的fieldId,value则为属性的值。比如传入的对象classDog{intage5;Stringnametom}那么两个data中的数据为{15,2tom},最后在constructStruct构建对象。编解码器
  在前面其实介绍过编解码器ThrfitCodec,为了符合标题,这里再啰嗦一遍。
  Thrift提供的编解码器顶层接口为ThriftCodec,提供了read和write方法publicinterfaceThriftCodecT{TheThrifttypethiscodecsupports。TheThrifttypecontainstheJavagenericTypeofthecodec。publicThriftTypegetType();ReadsavaluefromsuppliedThriftprotocolreader。paramprotocoltheprotocoltoreadfromreturnthevalue;notnullthrowsExceptionifanyproblemsoccurredwhenreadingorcoercingthevaluepublicTread(TProtocolprotocol)throwsException;WritesavaluetothesuppliedThriftprotocolwriter。paramvaluethevaluetowrite;notnullparamprotocoltheprotocoltowritetothrowsExceptionifanyproblemsoccurredwhenwritingorcoercingthevaluepublicvoidwrite(Tvalue,TProtocolprotocol)throwsException;}
  同时Thrift也为我们提供了常用的编解码器,足以应付我们业务的使用。比如常见的基本类型的编解码器,String类型编解码器StringThriftCodec:publicclassStringThriftCodecimplementsThriftCodecString{OverridepublicThriftTypegetType(){returnThriftType。STRING;}OverridepublicStringread(TProtocolprotocol)throwsException{returnprotocol。readString();}Overridepublicvoidwrite(Stringvalue,TProtocolprotocol)throwsException{protocol。writeString(value);}}
  IntegerThriftCodec:publicclassIntegerThriftCodecimplementsThriftCodecInteger{OverridepublicThriftTypegetType(){returnThriftType。I32;}OverridepublicIntegerread(TProtocolprotocol)throwsException{returnprotocol。readI32();}Overridepublicvoidwrite(Integervalue,TProtocolprotocol)throwsException{Preconditions。checkNotNull(protocol,protocolisnull);protocol。writeI32(value);}}
  关于结构体编解码器ReflectionThriftStructCodec前面一大篇幅都是介绍这个。
  不管是哪种编解码器都是非常依赖协议的,只是编解码器做了一层抽象屏蔽了细节,方便我们使用。协议与传输
  协议TProtocal和传输组件TTransport是紧密相连的,协议内部是持有TTransport的,而TTransport可以理解为传输层,是直接与输出数据容器buffer打交道的;比如使用最多的就是TNiftyTransport,内部会持有ChannelBuffer,包含了从netty数据流中获取的ChannelBuffer和之后写到客户端的空的ChannelBuffer。
  我们先简单介绍协议定义了哪些接口,然后找个接口来看如何进行数据传输的。Protocolinterfacedefinition。publicabstractclassTProtocol{protectedTTransporttrans;protectedTProtocol(TTransporttrans){transtrans;}privatebooleanserverSide;privateStringserviceName;getter,setterReadingmethods。publicabstractTMessagereadMessageBegin()throwsTException;publicabstractvoidreadMessageEnd()throwsTException;publicabstractTStructreadStructBegin()throwsTException;publicabstractvoidreadStructEnd()throwsTException;publicabstractTFieldreadFieldBegin()throwsTException;publicabstractvoidreadFieldEnd()throwsTException;publicabstractTMapreadMapBegin()throwsTException;publicabstractvoidreadMapEnd()throwsTException;publicabstractTListreadListBegin()throwsTException;publicabstractvoidreadListEnd()throwsTException;publicabstractTSetreadSetBegin()throwsTException;publicabstractvoidreadSetEnd()throwsTException;publicabstractbooleanreadBool()throwsTException;publicabstractbytereadByte()throwsTException;publicabstractshortreadI16()throwsTException;publicabstractintreadI32()throwsTException;publicabstractlongreadI64()throwsTException;publicabstractdoublereadDouble()throwsTException;publicabstractStringreadString()throwsTException;publicabstractByteBufferreadBinary()throwsTException;Writingmethods。。。。
  里面主要是数据的读和写方法,写和读方法是对应的就不贴了。读的方法基本都会配合TProtocolReader来使用,写的方法基本都会配合TProtocolWriter来使用。开始和结束消息的读取,开始读取方法参数的时候会在初始和结尾进行调用,可以获得方法的名字和请求的序号。开始和结束结构体的读取,在正式读取方法参数值的时候和读取完毕后进行调用,在TBinaryProtocal中可以认为是空实现,readStructEnd通常在readMessageEnd之前。开始和结束参数的读取,每次读取一个参数都会调用,readFieldBegin返回TField表示参数名称,类型和序号,基于此获取编解码器来读取参数值,最后再调用readFieldEnd。开始和结束集合的读取;
  挑个readI32,readString来看在TBinaryProtocal中的使用。privatebyte〔〕i32rdnewbyte〔4〕;publicintreadI32()throwsTException{byte〔〕bufi32rd;intoff0;if(trans。getBytesRemainingInBuffer()4){buftrans。getBuffer();offtrans。getBufferPosition();trans。consumeBuffer(4);}else{readAll(i32rd,0,4);}return((buf〔off〕0xff)24)((buf〔off1〕0xff)16)((buf〔off2〕0xff)8)((buf〔off3〕0xff));}
  这里的trans在前面说过,就是TNiftyTransport,由nifty包提供的。trans。getBytesRemainingInBuffer()表示的是内部持有的channelBuffer剩余字节数,即bufferEndbufferPosition;如果有四个字节就读取4个字节,否则读取所有;buftrans。getBuffer()是获取transport内部的的buffer数组;offtrans。getBufferPosition();是获取transport内部buffer当前读取到的位置,即bufferPosition;trans。consumeBuffer(4);则是transport内部buffer消费4个字节,即bufferPosition4;关于返回值,注意到16进制的0xff就是二进制的11111111,最终结果就是将四个字节拼接在一起构成一个int值
  关于readByte,readShort,readLong都是类似的。
  再来看readString:publicStringreadString()throwsTException{intsizereadI32();checkStringReadLength(size);if(trans。getBytesRemainingInBuffer()size){StringsnewString(trans。getBuffer(),trans。getBufferPosition(),size,UTF8);trans。consumeBuffer(size);returns;}returnreadStringBody(size);}
  首先读取四个字节构成的size,表示需要读取多少byte从而来构造string。在获取buffer和position,从而从buffer的position位置读取size个字节,构造出string;最后需要移动position再返回string结果。

2016年高考作文指导议论文的写作技巧高考作文的文体选择方面,议论文是大多数考生的选择。实际上,议论文也确实更稳妥,不容易偏题离题。下面是小编整理的议论文的写作技巧,希望对大家有帮助!【议论文的写作技巧】……小学助人为乐作文500字锦集6篇在平时的学习、工作或生活中,大家都不可避免地要接触到作文吧,作文是人们把记忆中所存储的有关知识、经验和思想用书面形式表达出来的记叙方式。那么你有了解过作文吗?下面是小编收集整理……工信部组织推荐2022年国家技术创新示范企业【大河财立方消息】4月24日,工业和信息化部发布关于组织推荐2022年国家技术创新示范企业的通知。通知要求,申请认定国家技术创新示范企业应在制造业重点领域具有关键核心技术攻关及……曲轴上市公司慎拓产线商用减势乘用放量新能源汽车成布局焦点财联社4月22日讯(记者陆婷婷)近期,已有曲轴上市公司开始公布Q1业绩情况,结合2021年报业绩表现来看,因重卡国标切换、整车电动化转型等,汽车核心零部件曲轴行情出现分化。国内……我心中的桃花源作文我心中的桃花源作文我心中的桃花源是个美丽的地方,与世隔绝,有森林、高山、湖波、阳光和沙滩。那里物产丰饶,不必为食物担心。渺无人烟,除我之外再无他人。陪我的只有一个木屋,一……关于诚信的700字作文诚信无形诚信无形诚信无形,却可以经天纬地;诚信无色,却可以耀人眼目;诚信无味,却可以在上下五千年、纵横海内外散发出醇厚的芬芳。无形、无色、无味的诚信有着撼人心魄的力量。近年……2021年教师节关于老师的作文教师节,旨在肯定教师为教育事业所做的贡献。一起来看看关于老师的作文,仅供大家参考!谢谢!关于老师的作文1老师是我们学习路上的明灯,为我们指引方向;老师是一位向导,带我们走……仙人掌品学网专稿未经允许不得转载最近,我爸爸带来了一盆别人送的仙人掌。我看了看这个仙人掌,它外层有一层锋利的针刺,防止别的动物去伤害它,就像是一个僵硬的贝壳。而里面却是绿色的。……长城导游词500字作文3篇长城越群山,经绝壁,穿草原,跨沙漠,起伏在崇山峻岭之巅,跨过黄河彼岸和渤海之滨下面是小编带来的长城导游词作文500字,希望对大家有帮助。篇一:长城导游词作文500字尊敬的……春天真美为题的350作文春天来了,金黄色的蒲公英在路边耀目,深紫的荞璐璐花在桃树下送情,蜜蜂在粉红色的杏花间歌唱,蝴蝶在淡蓝的天空中翩翩起舞,金翅鸟在刚放绿叶的柳树上细语,嫩黄的榆钱在春风中颤动,山鸡……运动会开幕式作文450字令全体同学都期待不已的学校运动会如期举行,但最最让人期盼的还是那隆重且盛大的运动会开幕仪式。运动会开幕的这一天,天高、云淡、风轻,是一个不错又难得的好天气,大家的好心情也……新鲜早科技丨华为全面进军商用领域曹操出行用户数破亿软银机器人21世纪经济报道数字经济课题组综合报道早上好,新的一天又开始了。在过去的24小时内,科技行业发生了哪些有意思的事情?来跟21tech一起看看吧。【巨头风向标】……
元旦小学作文元旦小学作文(一)元旦真热闹啊!看!人们都穿上了新衣服,每条大街小巷都有那么多五颜六色的身影在晃动,像河水一样流淌,前不见头,后不见尾。商店刚开门,人们便像开了闸的潮水一……六年级日记端午节日记(五)我期盼已久的端午节终于要到了。妈妈告诉我端午节是在每年的五月初五过,这让我铭记于心。好不容易,时间到了端午前一天。外婆要开始包粽子了!我的小弟和表弟兴奋不已,迫不及待地跑……程维终于怕了,滴滴回应被约谈深刻反省,将主动降低抽佣史无前例!国内最大的吸血工厂竟然低头了!近日,滴滴官方发布声明,根据5月14日多部门约谈要求,滴滴将自查极端抽佣情况,切实保障司机利益,主动降低抽佣比例!以往……必备观察日记集合6篇一天的时间即将结束了,相信你一定有很多值得分享的经验,因此我们要写好日记了。快来参考日记是怎么写的吧,以下是小编收集整理的观察日记6篇,仅供参考,欢迎大家阅读。观察日记篇1……书香满落春风里初中作文如今已是春意浓浓,花香四溢,禁不住品嗅,嘻!竟有一丝书香卷气!在花丛中寻觅着让人垂涎三尺的气息,竟不可得!忽然间,瞧向那人来人往的一角,竟是书香满琅。只见人人都在那捧着一……关于毅力的作文不经风雨,怎么见到阳光后的明媚?无论生活有多么的艰苦,道路有多么的险阻,让我们学会用正确的心态面对人生的磨难,用钢铁般的意志与顽强的奋斗精神迎接生活的各种挑战吧!下面小编为大家……美化环境作文三篇引导语:在环境问题日益严重的今天,做好保护环境的相关事情是非常重要的,那么要怎样写一篇有关美化环境的作文呢?接下来是小编为你带来收集整理的文章,欢迎阅读!美化环境作文一美……为学习制定目标作文600字学习的方向,掌握在自己的手中。每一位同学都应该为学习设定好目标,找到学习的方法。现在我们已经步入九年级了,九年级又是一个新学期,也是一个良好的开端。许多同学都为自己设定了……关于描写瀑布的500字作文作文一:瀑布我的家乡在广西崇左市,那里风景优美,四季宜人,是一个有着众多风景名胜的好地方。家乡的风景名胜多得数不胜数,有小巧玲珑的石景林,有雄伟的友谊关,有斜矗江心的归龙……难忘的一件事600字作文【篇一:难忘的一件事】岁月,无痕。它悄悄的,流逝了。似沙漏,缓缓流着;如花瓣,片片飘零。在这些流逝的岁月中,我一天天成长,成长。成长过程中,我经历过许多事,正是这些事,才……关于圣诞节的英语作文圣诞节的传说关于圣诞节的英语作文:圣诞节的传说itissaidthattherewasagoodnessmanwentbrokehisdomain。helivedahardlifea……清明节扫墓日记600字3篇是一年清明时,霏霏细雨,点点愁思,几多离人泪!下面是小编给大家分享的清明节扫墓日记,让我们一起来看看吧!清明节扫墓日记一又到了每一年一次的清明节,爸爸妈妈带着我回房……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网