• 阅读笔记(八)


    关于软件系统的架构设计,是一个太多人喜欢讨论的问题,尤其是对软件开发不了解的人士来说,总是被各种各样的概念绕来绕去。从更高的层次,更大的视野研究架构设计的一些专家(如Martin Fowler、Chris Richardson)能够很清晰的列出这些众多概念的区别,而身在开发一线的我们更多的是对这些概念有一些感性的、朴素的认识。将之内化到自己的工作中去,才能更好的发挥架构的优势。

    本文将简单谈谈SOA和MSA的概念,并简单列举一下如果使用Java来构建一个微服务系统时所会遇到的一些概念。本文只是「Yet Another」叙述微服务的文章,而且观点并没有很严谨,希望能让读者对微服务和SOA留下一个感性的认识,如果有什么不对的地方,还请轻拍。

    微服务和SOA的区别

    所以,到底SOA和微服务有什么区别?

    短答案:微服务是SOA发展出来的产物,它是一种比较现代化的细粒度的SOA实现方式。

    微服务就是这样的一个「概念」,说白了,它不过就是近些年火起来的有一个名词而已,一时间仿佛整个行业都在讨论它,仿佛终于找到了银弹。这个时候SOA看待微服务大概就如同当年的Friendster和Myspace看待Facebook一样——大家都忘了社交网络这个东西并不是Facebook发明的。你再谈如何使用SOA去构建一个系统,就像是在谈一个过气的明星,人们会认为你已经落伍了。但真的是这样的吗?

    MSA is a SOA

    较早实践微服务的公司Netflix就曾经称他们构建的架构是「细粒度的SOA」

    讨论「微服务和SOA的差别」的意义远不如讨论「微服务和单体系统的差别」更大,因为他们的区别实在有点微妙。此外,互联网近些年的发展,越来越朝去中心化的方向前进了,就像今天的IT工程师不需要像律师、教师那样,需要得到某些机构的认可才能更好的开展工作,这一方面意味着门槛的降低,另一方面也意味着更多的概念没有一个权威的声音来对它进行定义,使得每个人可以根据自己的需求做出不同的调整。

    微服务和SOA都是这样背景下的产物,并没有一个权威的定义,来说明它们各自包含了什么东西,使用什么的方法进行系统的构建。但是,还是可以从最大的范围来对比它们的不同,当我们今天说出这两个概念时,其区别往往没有那么大,但SOA是有一定的历史了,在历史上的SOA往往意味着更多的东西,而这些是现在很多人在做架构设计时不会采用的。

    MSA vs SOA

    1. 最多被人谈起的,应该算是ESB了
    万能的ESB(图片来自Wikipedia)

    ESB(enterprise service bus)曾经着实跟随着SOA火了一阵子,第一次知道它是一个朋友在一家物流公司工作,说他们用了一个很高级的玩意儿,叫企业服务总线,接着给我灌输了一堆ESB的理念。当时感觉这玩意儿太牛了,设计理念也很厉害。

    从名称就能知道,它的概念借鉴了计算机组成原理中的通信模型——总线,所有需要和外部系统通信的系统,统统接入ESB,岂不是完美地兼容了现有的互相隔离的异构系统,可以利用现有的系统构建一个全新的松耦合的异构的分布式系统。

    但,实际使用中,它还是会有很多的缺点,首先就是ESB的本身就很复杂,大大增加了系统的复杂性和可维护性。其次就是由于ESB想要做到所有服务都通过一个通路通信,直接降低了通信速度。

    而在现代的微服务中,往往是一个「富终端、瘦通信」(Smart endpoints and dumb pipes),使用轻量级的通信机制,而每个终端(服务)有自己的处理逻辑,它知道它要找的服务在哪里,不需要在通信的链路上做什么事情。

    然而,ESB是一个历史产物,用今天的眼光看待它,并且将之当做SOA的一个标签是不合理不公平的。

    2. 服务化的概念和服务的尺寸

    如前所述,SOA的出现其实是为了解决历史问题:企业在信息化的过程中会有各种各样互相隔离的系统,需要有一种机制将他们整合起来,所以才会有上边所述的ESB的出现。同样的,也造成了SOA初期的服务是很大的概念,通常指定的一个可以独立运作的系统(这样看,好像服务间天然的松耦合)。这种做法相当于是「把子系统服务化」。

    而微服务没有历史包袱,轻装上阵,服务的尺寸通常不会太大,关于服务的尺寸,在实际情况中往往是一个服务应该能够代表「实际业务场景中的一块不可分割或不易分割的业务实体」。将服务的尺寸控制在一个较小的体量可以带来很多的好处:

    1. 更易于实现低耦合、高内聚
    2. 更易于维护
    3. 更易于扩展
    4. 更易于关注实际业务场景
    3. 通信协议(好吧,我实在编不下去了)

    如今越来越多的工程开始使用RESTful来作为API的设计的基础,但仅仅几年前还有大把的API使用SOAP、WSDL等基于XML的重量级协议的Web Service。

    这点和上文说到的2点其实大同小异,仔细想想,它们都是由于历史原因造成的,同样的,通信协议经过这些年的发展,现在主流的基本上了两种:

    1. 文本协议
      使用最广泛的多是基于HTTP的RESTful规范
    2. 轻量级二进制协议
      Thrift、Protobuf,或者任何自定义的轻量级协议

    要解决的问题

    大家都在讨论微服务,造成了当有人要构建一个系统,往往会第一时间想到使用它,较少有人会去想为什么要用微服务,是不是有更好的选择。

    没有银弹

    软件工程是一个处处有坑的事情,但MSA不是银弹,并不是所有的软件系统都适合。它有自己适应的场景和不足之处,下面根据自己的理解列出一些系统的需求,如果你的系统有这方面的需求,那么可以考虑使用微服务来构建你的系统。

    复杂性

    顾名思义,微服务首先强调的是服务粒度比较小,这就带来了一个直接好处:实现简单。

    如果你判断你的系统需要有很多截然不同的功能模块,复杂的业务逻辑,业务目标多种多样,那么你可以开始考虑使用MSA将你的系统分解成概念上独立的服务,这样一来开发工作的难度可以直接的降低了。当然,与此同时你要面对的是另外一种复杂性挑战——从概念上分解和管理这些服务本身就是一件十分复杂的工作。好在现在开源社区有很多较完善的服务治理的框架和解决方案,正可以用来解决这方面的复杂性问题。

    相反,假如你要做一个论坛系统,或者一个简单的电商网站,并没有进行大面积推广的计划,预计用户规模在可预见的范围内不会超过10万。那么你需要的不是微服务,而是可以快速开发并上线的架构,这种情况单体应用最合适,也有很多的开源解决方案可以用来开发MVP。

    可维护性

    微服务的细粒度服务和分布式部署的特点,带来的一个好处是:可独立维护。

    如果你的系统需要持续的改进,以配合业务的不断发展,那么可以考虑使用MSA来做系统的架构。例如,你们正在做一个电商网站,经常要做各种各样的活动,优惠条件、优惠力度、甚至优惠的计算方式都经常在变,这所有的变化不可能在系统设计的时候完全考虑到,当需要开发介入时,MSA的优点就体现出来了。

    服务的分离所遵循的很多原则(如SRP、开闭原则)正是为这种改变所提出的,根据这些原则,你的系统里可能有一个服务叫「订单服务」,所有的改动都只需要在这个服务内进行,或者更进一步,你有一个专门处理活动的服务,只需要很少的开发和测试的工作量就可以实现。

    C10K、C100K。。。

    高并发这个概念快变得烂大街了,不同的高并发场景需要的解决方案千差万别,同时它也是一个系统工程,而不是通过某一个方面就能解决的。如对于一个做内容的网站,高并发带来的直接挑战是大量数据(图片、文本)的获取,而对于写的需求相对而言并不会很高,所以CDN、缓存、网页静态化等都是可以采用的软硬件解决方案;而对于电商类的交易系统,更重要的是保证系统的快速响应、持续可用、最终一致、和水平扩展,所以NIO、分库分表、缓存、API升降级、负载均衡都是可以采用的方案。

    当然,本文的重点是MSA,所以这里只从架构的角度讲一下MSA对于解决高并发问题的优势。由于MSA通常是分布式部署,通过服务注册中心实现服务的发现,服务具体部署的机器对于服务的调用方来说是透明的,然后通过客户端或者服务端的软负载均衡,可以在某个服务的压力大的时候直接添加机器实现水平扩展,对于性能的提示在某个范围内可以认为是线性的。从架构的角度,微服务是解决某一类高并发的较好的解决方案。

    同时,高层的架构设计只能从大局上解决这个问题,比如你设计了一个很完善的分布式系统,但好多的服务经常出现内存泄漏,动不动机器就当掉,那多好的架构都于事无补。

    框架选择的玄学

    虽然Java的框架还没有多到JS那么离谱,但相同或相似的功能通常都会有两个或两个以上的选择,有的需要多选其一,有的可能要组合使用。如何在这些名目繁多的框架中选择出来适合自己的框架十分困难,每个人心中都有自己的一套的价值观,快变成了玄学了。

    在github搜索「framework」的结果

    有一派的存在主义哲学认为,人是自由的,这体现在人有选择的自由,一个人做的每一个选择都成为他未来的自己的一个组成部分。放在架构设计上也适用,你在做各种各样的选择时,也一步步地成就了你要构建的那个系统的样子。

    Java中的微服务

    虽然MSA其本身不排斥多语言的异构系统,实际场景中也会有多语言开发的例子,但多数情况下,很多人还是习惯于系统中大多数的服务都是用相同的语言进行开发。在Java的生态中,已经有很多十分成熟的,可以拿来实现MSA的中间件,比较出名的有:Spring全家桶(基于Netflix)、Dubbo(国内十分流行)、Thrift(需要自己实现一些基础的东西)。
    通常,MSA的实现通常要满足下面几个条件:

    1. 服务足够的小,需要根据自己的实际需求决定服务的大小。
    2. 服务可以独立开发、部署、测试。
    3. 使用轻量级通信方式。
    4. 数据分离

    实际场景中的选择

    在实际的MSA的实践中,会遇到各种各样的选择,To be or not to be,被这个问句困扰着的不止哈姆雷特,还有很多开发者。实际场景中会遇到的选择包括但不限于以下几点,可以拿来作为一个checklist。
    这并不是一个完整的列表

    • 具体细节的实现方式
      从代码级的角度看,主要是具体细节的实现方案,代码的好与坏很难用一个定量的标准去衡量,但GOF的设计模式是一个很好的开始,「重构」那本书中也讲到了很多「代码中的坏味道」。多数情况下,这里讲到的坏代码并不是指的性能,而是指其可读性与可扩展性。

    • 基础设施
      任何软件系统都是要部署到具体的基础设施上去的,关于基础设施的部署也有很多的选择,如:PC vs Docker、Apache vs Nginx、Tomcat vs Jetty。

    • 微服务框架

      1. Spring全家桶
        用起来很舒服,只有你想不到,没有它做不到。
      2. Dubbox
        很多国内的企业还在用,可以支持RESTful风格的API,但更多的还是会使用Dubbox的默认的基于RPC的API,调用远程API像调用本地API一样。这样做无疑带来了很多优势,但同时其基于接口的方式增加了服务间的耦合,怎么说呢,各有利弊。
      3. Thrift
        如果你比较高冷,完全可以基于Thrift自己搞一套抽象的自定义框架。
    • 同步vs异步
      在跨服务的业务逻辑的实现上,使用基于消息的异步调用,还是使用保证结果的同步方案。

    • 数据服务
      内存数据库 vs 持久化数据库(Redis vs MySQL)
      关系型数据库 vs 非关系型数据库(MySQL vs Mongo)
      传统数据库 vs 分布式数据库(MySQL vs F1)
      非关系型数据库又有如KV数据库,文档数据库,图数据库等。
      由于MSA提倡服务间的数据隔离,往往不同的服务使用不同的数据源,这就会直接导致数据聚合查询比较困难的问题。进行数据聚合又有几种不同的方案(如CQRS)。

    • 日志分析
      日志分析也是有很多的成熟解决方案(如ELK)。

     
  • 相关阅读:
    Can't remove netstandard folder from output path (.net standard)
    website项目的reference问题
    The type exists in both DLLs
    git常用配置
    Map dependencies with code maps
    How to check HTML version of any website
    Bootstrap UI 编辑器
    网上职位要求对照
    Use of implicitly declared global variable
    ResolveUrl in external JavaScript file in asp.net project
  • 原文地址:https://www.cnblogs.com/tianxiayoujiu/p/10916860.html
Copyright © 2020-2023  润新知