`
QING____
  • 浏览: 2233433 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

《架构师》期刊摘要(2015年)三

 
阅读更多

一、微服务解决我们哪些痛点呢?

    1)技术架构、平台升级难:传统的单体式架构系统倾向于采用统一的技术平台或者方案解决所有的问题;而微服务的异构性,可以针对不同的业务特征选择不同的技术方案,有针对性的解决具体的业务问题。

    对于单体式架构系统,初始的技术选型严格限制将来采用的不同语言或者框架的能力,没有完备的功能测试集,很难平滑的完成替换,而且系统规模越大,风险越高。基于微服务架构,使我们更容易在遗留系统上尝试新的技术或者解决方案。

    2)测试、部署成本高

    单体式架构系统,多个功能组件运行在一个进程中,因此系统中任何程序的改变,都需要对整个系统重新测试并部署。而对于微服务架构而言,不同服务之间的打包、测试或者部署等,与其他服务都是完全独立的。对某个服务所做的改动,只需要关注服务本身。从这个角度来说,使用微服务后,代码修改、测试、打包以及部署的成本和风险都比单体式架构系统减低了很多。

    3)可伸缩性

    单体式架构系统由于单进程的局限性,水平扩展时只能基于整个系统进行扩展,无法针对某一个功能模块按需扩展。而服务架构则可以完美的解决伸缩性的扩展问题。系统可以根据需要、实施细粒度的自由扩展。

    4)构建全功能团队难

    康威定律指出:一个组织的设计成果,其结构往往对应这个组织中的沟通结构。传统的开发模式在分工时往往以技术为单位,比如UI团队、服务端团队和数据库团队,这样的分工可能会导致任何功能上的改变都需要跨团队沟通和协调。而微服务则提倡围绕服务来分工,团队需要具备服务设计、开发、测试到部署所需要的所有技能。

    5)异常破坏性大

微服务架构同时也能提升错误的隔离性,比如某个服务的内存泄露,只会影响自己,其他服务能够继续正常的工作。与之形成对比的是,单体式架构中如果有一个不合格的组件发生异常,有可能会拖垮整个系统。

 《从单体架构到微服务》(2015年5月)

二、序列化与反序列化:

    序列化:将数据结构或者对象转换成二进制字节流的过程。

    反序列化:将序列化过程生成的二进制字节流转换成数据结构或者对象的过程。

    数据结构和对象:对于类似于JAVA这种完全面向对象的语言,工程师所操作的一切都是对象(Object),来自类的实例化,那么序列化就是将这些对象转换成二进制流可以保存在磁盘或者在网络中传输;反序列化正好相反,通过从磁盘或者网络中读取二进制流并转换成内存中JAVA对象的过程。

 

    序列化协议特征:

    1、通用性

    1)技术层面:序列化协议是否支持跨平台、跨语言。如果不支持,在技术层面上的通用性就大大降低。

    2)流行程度:序列化和反序列需要多方参与,很少人使用的协议往往意味着昂贵的学习成本;另一方面,流行度低的协议往往缺乏稳定而成熟的跨语言、跨平台的公用包。

 

    2、强壮性/鲁棒性(影响强壮性的几个原因)

    1)成熟度不够,一个协议从制定和实施,到最后成熟往往是一个漫长的阶段。协议的强壮性依赖于大量而全面的测试,对于致力于提供高质量服务的系统,采用处于测试阶段的序列化协议会带来很高的风险。

    2)语言/平台的不公平性:为了支持跨平台、跨语言的功能,序列化协议的制定者需要做大量的工作,但是当所支持的语言或者平台之间存在难以调和的特性的时候,协议制定者需要做出一个艰难的决定---支持更多人使用的平台或者语言,亦或支持更多的语言、平台而放弃某些特性,这个时候,协议制定者可能会牺牲某些平台、语言的“强壮性”。

 

    3、可调式、可读性(涉及到易用性问题)

    序列化和反序列的数据正确性和业务正确性的调试往往需要更长的时间,良好的调试机制会大大提高开发效率。如果序列化后的数据人眼可读(human readable),这将大大提高调试效率,XML和JSON就具有人眼可读的有点。

 

    4、性能

    1)空间开销:序列化需要在原有的数据上加上描述字段,以为反序列化解析之用。如果序列化过程引入的额外开销过高,可能会导致过大的网络、磁盘等各方面的压力。对于海量分布式存储系统,数据量往往以TB为单位,巨大的额外空间开销意味着高昂的成本。

    2)时间开销:复杂的序列化协议会导致较长的解析时间,这可能会使得序列化和发序列化阶段称为真个系统的瓶颈。

    3)可扩展性/兼容性

    互联网时代,业务系统需求的更新周期见得更快,新的需求不断涌现,而老的系统还是需要继续维护。如果序列化和发序列化具有良好的可扩展性,支持自动增加新的业务字段,而不影响老的服务,这将大大提供系统的灵活度。

    4)安全性/访问限制

 

    5、序列化和反序列化的组件

    1)IDL(Interface description language,接口描述语言)文件:参与通讯的各方需要对通讯的内容做相关的约定。为了建议一个与语言和平台无关的约定,这个约定需要采用与具体开发语言、平台无关的语言来进行描述,这种语言被称为IDL。

    2)IDL Compiler:用于编译IDL,用于生成各个语言、平台可见的接口。

    3)Stub/Skeleton Lib:由Compiler生成,用于负责序列化和反序列化的工作代码。Stub是一段部署在分布式系统客户端的代码,一方面接收应用层的参数,并对其序列化后通过底层协议栈发送到服务端,另一方面接收服务端序列化后的结果数据,发序列化后交个客户端应用层;Skeleton部署在服务端,其功能与Stub相反,从传输层接收序列化参数,反序列化后交给服务端的应用层,并将应用层的执行结果序列化后最终通过网络传递给客户端Stub。

    4)Client/Server:应用层代码,他们面对的是IDL Compiler生成的接口文件的具体实现。

    5)底层协议栈:序列化后的数据通过底层的网络(协议栈,比如传输层、网络层、链路层等)传递,通常面向TCP、Http协议等。

 

    Thrift:

    Facebook开源提供的一个高性能、轻量级RPC服务框架,其产生正是为了满足当前大数据量、分布式、跨语言、跨平台数据通讯的需求。但是,Thrift不仅仅是一个序列化协议,而是一个完整的RPC框架。相对于JSON和XML而言,Thrift在空间开销和解析性能上都有比较大的提升,对于性能要求比较高的(性能优先)分布式系统,它是一个优秀的RPC解决方案,但是由于Thrfit的序列化被嵌入到Thrfit框架中,框架本身并没有透出序列化和发序列化的结构,这导致很难与其他的传输层协议共同使用(例如Http协议,Thrift使用TCP协议,而且改造其服务传输模式非常困难)。

    个人建议,非性能优先、openAPI、大数据传输协议,不建议使用Thrift,特别是普通的业务系统,感觉不好用。

 

    Protobuf:

    非常优秀的序列化、反序列化框架,使用IDL和编译器,生成传输协议的代码(目前也支持RPC接口,参见gRPC),序列化数据非常简洁、紧凑,与XML相比,其序列化之后的数据量要小很多。解析速度快,而且易于使用。所以我们推荐Protobuf作为大家的序列化、反序列化框架。Protobuf是一个纯粹的展示层协议,可以和各种传输协议一起使用,在JAVA平台上基本上是通用和标配。缺点是支持的平台相对较少,使用Protobuf需要一些外部的框架支持、需要额外的一些代码开发。

 

    Avro:

    Avro的产生解决了JSON的冗长和没有IDL的问题,Avro属于Apache Hadoop的一个子项目,在大数据体系中通常使用Avro作为数据的序列化和发序列化,而且易于存储和解析。

 

    官方有一些基准测试的结果,基于时间和空间的性能比对梯图:

    1)XML序列化(Xstream)无论在性能和简洁性上都比较差。

    2)JSON序列化(jackson)表现居中,比Protobuf、thrift要差一些,但是比java自带的序列化要好不少。

    3)Thrift和Protobuf相比,在时间开销方面都一定的劣势。

    4)Protobuf和Avro在两个方面都表现的比较优越。

    所以如果仅从序列化、反序列方面考虑,Protobuf和JSON仍然是主流的选择,Protobuf应该是JAVA平台的首选,考虑跨语言的话JSON首选。如果考虑到RPC层面,Thrift可以考虑。

 

    1、对于公司间(异构系统、开放API)调用,如果性能要求在100ms以上是可以接受的,基于XML的SOAP协议是一个值得考虑的方案。(Web Service)

    2、基于浏览器的Ajax或者基于Mobile App与服务器端交互的请求,JSON协议是首选。这对性能要求不太高,或者以动态类型语言为主,或者传输数据载荷较小的场景,JSON也是非常不错的选择。(简单而言,基于Http协议的互联网、移动互联网、类似于Gateway的服务,且不存在较大数据传输的场景,建议JSON首选)

    3、对于调试环境比较恶劣的场景,采用JSON或者XML能够极大的提高效率,减低系统开发成本;这是基于数据可读性方面的考虑。

    4、当对性能和简洁性有极高要求的场景,或者内部服务间通讯的,Protobuf、Thrift、Arvo之间可以斟酌考虑。(跨语言、平台的话,需要比较它们的适用性和易用性)

    5、对于T级别的数据持久化场景,Protobuf和Avro是搜要选择,因为这两个协议序列化后数据尺寸较小、而且易于持久化。如果持久化后的数据存在于hadoop生态中,Avro是更好的选择。

    6、由于Avro的设计理念偏向于动态类型语言,对于动态语言为主的应用场景,Avro是更好的选择。

    7、非Hadoop平台的数据,特别是JAVA平台之间的序列化,Protobuf几乎是唯一选择。

    8、如果出了序列化和反序列化,还需要高效的RPC框架,Thrift更加适合。(前提是,接口协议不应该频繁的变更;对于公司内部的业务接口,通常Thrift不合适;但是open API类型的基础服务,还算适用)

    9、如果序列化之后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,Protobuf可以优先考虑。

《序列化与反序列化》(2015年6月)

三、架构之重构的12条军规(备注:值得一看)

    1、确定重构的目的和必要性:明确重构的目的是为了满足业务需求,并且是不得不做的最佳方案。有时候经过分析就会发现,也许还有其他的解决方案(而非重构),比如增加计算资源、或者重构的目的不是为了业务需求,那就没有必要了。

    1)架构重构的原因是什么,是为了满足业务的需求还是只是觉得架构不好看?

    2)除了架构重构之外,还有其他备选方案吗?是否都分析过这些方案的利弊?

 

    2、定义“重构完成”的界限:界定怎么才算“重构”完成了,目标要有数据量化,或者能够测量的方法。如果需求不明确,负责重构的团队也没有明确的目标,不能以重构的时间或者主观的判断为结束的依据。

    1)重构的目标可以量化,或者可以测量吗? 2)重构完成的标准是什么?得到业务部门或者领导的认可了吗?

 

    3、渐进式重构:现在软件研发最流行的就是快速迭代、持续交付、尽早反馈。这同样可以用在架构的重构上,重构过程的难度不亚于构建一个新的产品,所以在设计重构的时候,要引入持续交付的流程,每一个重要步骤或者模块都要快速部署并得到反馈,以便评估重构的效果,即使作出策略调整。

    1)能否把重构过程分解成小的迭代,每一次改进都能尽快得到反馈?

    2)重构过程中的效果能够定期展示给业务部门或者领导吗?(我感觉作者,就是个“权威”信仰派的,哈哈)

 

    4、确定当前的架构状态:在启动重构之前,需要对当前架构的状态有清晰的了解,也就是设定好基准,以便评估重构的效果。

    1)你了解当前的架构设计吗?它的设计初衷和之前的选型方案知道吗?

    2)你能给架构设定一个基准状态吗?

 

    5、不要忽略数据:

    架构重构的本质就是对于数据流的重构,重构之后的系统对数据的存储、处理、分析等功能是否有影响,在重构过程中,考虑依靠数据甚至实际的数据来验证重构的效果,提供评估的支持。

    1)业务数据的需求在重构设计中有体现吗?

    2)重构过程中能否通过实际数据来验证效果?

 

    6、管理好技术债务:

    架构重构往往是为了偿还技术债务,所以请不要在技术重构的过程中制造新的技术债务。技术债务就想信用卡一样,会有很高的利率。组织应该培养一种保证设计质量的文化。应当鼓励重构、同时也应该鼓励持续设计以及其他有关代码质量的实践。

    1)团队对技术债务有跟踪和备忘机制吗?还是开发人员可以随意的产生债务?

    2)针对技术债务有定期的培训、回顾机制吗?

 

    7、远离那些虚荣的东西(例如使用“热门”的技术栈)

    架构的重构过程应该以目标为导向,换句话说“注重实效”。对于技术人员来说,一个经常被轻视的问题在于,喜欢追求新鲜的热门技术,这其实是个好事情,说明技术人用于创新,不断接受新技术。但是对于架构的重构这样的关键性人物来说,是不是新技术并不重要,重要的是能不能实现重构的目标。对于新技术来说,虽然热度大,但是人才储备不足,大家踩过的坑还不多,积累的失败教训和成功的经验还不够,在这种情况下,建议大家不要头脑一热就上马新技术,应该客观冷静的评估新技术与成熟技术对架构重构的影响和效果,以数据和经验来说话,而不要追求赶时髦。

    1)重构的技术选型是否有详实的数据和专家评估?

    2)选用的技术是否有良好的人才积累和足够的经验支持?你是不是实验小白鼠?

    3)技术选型时,是否至少有两个方案待评估?有没有成熟的技术方案?

 

    8、做好准备面对压力:

    这条军规更像是对架构师们的心理建议。对于架构重构来说,压力源于多个方面:管理层、团队成员、同级部门等。说白了,架构重构对个人来说往往是出力不讨好的事情。和做一个新产品能够取得很高的赞赏相比,重构的成绩往往并不受领导重视,而是出了问题还要承担很大的责任。从软件开发角度看,做新产品是0到1,而架构重构是-1到1,复杂性和难度通常更大。

    1)架构的重构是否得到管理层(特别是最高管理层)的支持?他们是否对重构的时间、任务量有直接的认识?

    2)你的重构计划中是否包含一些可以量化的成果?是否定期向管理层展示这些成果?

 

    9、了解业务:

    虽然看起来是一句废话,但是RaffiKrikorian特意把这条提出来一定是有道理的。架构重构的最终目的是改进业务,所以对业务的了解将有助于架构师和技术人确定重构目标的优先级和关键路径。比如,我们需要指导哪些关键业务的架构师不能碰的,哪些业务之间是互相关联的,哪些业务的架构师需要优先重构的....除了了解业务本身,我们还需要了解“人”,表面上管理层是重构目标的裁决者,但实际上业务部门的人才是。技术人需要了解他们的业务需求,并将其转化成重构目标。通过这种方式,架构重构的意义才能得到具体的体现。

    1)是否与业务部门就架构重构所能实现的业务目标进行过充分的讨论和确认?

    2)是否对关键业务和优化重构的业务进行了确认?

 

    10、做好面对非技术因素的准备:

    恩.....这又是一个不那么让人舒服的建议。不管你是否愿意相信,技术在架构重构的影响因素中并不是最高的,我们还会涉及到商业利益、管理层偏好、大客户影响、办公室政治、站队问题等等,对于架构师和技术人来说,这些因素往往不是他们所能掌控的。我们能做的就是,与利益相关者设定重构目标,然后,根据不同的影响因素,调整目标。请记住,不要死扛这个目标,当有人提出不同的意见时,要坦诚地和他们交流,并告知他们如何采纳意见,那么重构目标就会发生变化,然后让其他利益相关者也知道这些变化。非技术因素的影响是客观存在的,而且从商业层面来说也是合理的,所以技术人来说要学会适应。

    1)当非技术因素影响架构重构是,你是否对目标做了调整并告知了利益相关方?

    2)你是否准备以开放而不是地址的心态对待非技术因素的影响?

 

    11、对于代码质量有所掌握:

    架构的重构对代码质量要求更高,一方面是重构过程对BUG的容忍性比新产品的研发更低,另一方面也决定了下一次重构的难以程度。代码审查时一个非常好的办法。

    1)团队成员是否对代码质量有足够的重视?是否有奖惩措施?

    2)团队内部是否有代码质量的标准文档和审查流程?

 

    12、让团队做好准备:

    拥抱未知的恐惧吧,或好或坏!

《架构之重构的12条军规》(2015年6月)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics