阅读 807

漫谈技术演进和思考

一、什么是架构

1、架构的目标
  • 抽象来说,架构的目标是解决利益相关者(stakeholder)的关注点(concerns)

  • 具体来说,架构是目标是:管理系统的复杂性、易变性和不确定性,以确保在长期的演化过程中,一部分变化会对其它部分产生不必要的负面影响(防止劣化);让易变的部分能够频繁地变化,但是对其它部分的影响尽可能的小。

2、利益相关方 & 关注点
  • 各个业务的PM,RD、QA、运维和和运营等都是利益相关方;
  • PM关注需求快速上线、RD关注需求实现、及时上车 和 无bug、QA关注需求质量、运维关注服务稳定、运营关注关注用户反馈。
  • 架构师要充分和利益相关者沟通,深入理解他们的关注点和痛点,并出架构解决这些关注点。
3、架构师之路
  • 拥有全局视角 和 系统思维(System Thinking),深入理解整个价值交付链,从业务需求、研发、测试、集成,到部署运维;架构师要站在系统高度去优化整个价值交付链,保障快速和高效的价值传递;
  • 关注每个环节的闭环反馈;用数据说话;根据数据和反馈,推动系统、流程和体验的持续的提升和改善;
  • 鼓励勇于承担责任,冒险试错和持续提升的文化;

二、研发架构的演进

1、概述

  • 互联网PC时代没有明确的前后端概念,这个时期,开发人员也没有明确的前后端边界,前端页面和后端逻辑都写在一个工程里;如早期的JavaWeb开发,既要写HTML、CSS、JavaScript,还要写Java;
  • 随着业务的发展,开发者同时处理前后端工作,效率越来越低;而移动互联网中Android和iOS的爆发,庞大流量的涌入,业务变得越来越复杂,研发团队急速扩张,这些都急速加剧了前后端分离;
  • 我们需要一个全新的研发架构,既要保证用户在前端的体验,又要保证后端服务的高并延;将原有的团队拆分成前后端团队,让两端的工程师更加专注自己的领域,独立治理,然后构架出一个全栈式、精益求精的研发团队。

2、从移动端、前端到大前端

  • 移动互联网时代,Android和iOS手机操作系统横空出世,他们被定义为客户端;在客户端高歌猛进的同时,前端日新月异,Angular、React、Vue ... 等各种各样的新技术层出不穷;
  • 随着业务的急速发展,对业务快速交付的要求越来越高,Hybrid开发模式、跨端技术方案(React Native、Weex、Flutter)也应运而生;
  • 此后,客户端和Web端的边界越来越模糊,渐渐演化成大前端。对于后端、PM等来说,客户端和Web端都是前端。

3、从后端到大后端

  • 得益于移动互联网的爆发式增长,海量的前端请求都聚集到后端;后端单个接口QPS从0.1k、到1k、1w甚至到10w+;百万、千万PV,百亿级流量已是常态;后端面临越来越多的挑战;
  • 后端不是简单的BBF(Backend For Frontend,服务于前端的后端),而是在承受诸多挑战:高并发、低延迟、负载均衡、分布式、消息队列、安全等。
  • 后端的软件架构也在激进演化,从单体架构到分布式应用,到微服务,甚至未来会走向Serverless架构。

三、后端软件架构的演进

后端的软件架构分以下四种(主流的、炙手可热的依然是微服务架构):

1、单体架构

  • 初级结构,典型的三级架构,前端(Web端/客户端) + 中间业务逻辑层 + 数据库层,这是一种典型的Java Spring MVC或者Python Drango框架的应用;
  • 单体架构的应用比较容易部署、测试,但是缺点也比较明显:
    • 复杂性高
    • 技术债务
    • 部署频率低
    • 可靠性差:某个应用Bug,例如死循环、内存溢出等,可能会导致整个应用的崩溃。
    • 扩展能力受限:单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。
    • 阻碍技术创新:单体应用往往使用统一的技术平台或方案解决所有的问题, 团队中的每个成员都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。

2、分布式应用

  • 核心是:中间业务逻辑层分布式 + 数据库分布式,是对单体架构的并发扩展,将一个大的系统划分为多个业务模块,业务模块分别部署在不同的服务器上,各个业务模块之间通过接口进行数据交互。
  • 数据库也大量采用分布式数据库,如Redis。通过 LVS/Nginx 代理应用,将用户请求均衡的负载到不同的服务器上。
  • 分布式应用大大提高了系统负载均衡能力,极大满足高并发的需求,优点如下:
    • 降低了耦合度:把模块拆分,使用接口通信,降低模块之间的耦合度。
    • 责任清晰:把项目拆分成若干个子项目,不同的团队负责不同的子项目。
    • 扩展方便:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
    • 部署方便:可以灵活的进行分布式部署。
    • 提高代码的复用性:比如Web、Android,iOS使用同一个Service层。
  • 分布式应用的缺点:
    • 各个系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。

3、微服务架构【当前の主流】

  • 主要是中间业务逻辑层的解耦,将系统拆分成很多小应用(微服务),微服务可以部署在不同的服务器上,也可以部署在相同的服务器上的不同的容器中,单应用的故障和负载都不会影响到其他应用,其代表框架有Spring CloudDubbo等。
  • 微服务架构的优势:
    • 易于开发和维护:一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量较少
    • 单个微服务启动较快:单个微服务代码量较少, 所以启动会比较快。
    • 局部修改容易部署:对某个微服务进行修改,只需要重新部署这个服务即可。
    • 技术栈不受限:
  • 微服务架构的缺点:
    • 运维要求较高:更多的服务意味着更多的运维投入。在单体架构中,只需要保证一个应用的正常运行。而在微服务中,需要保证几十甚至几百个服务服务的正常运行与协作,这给运维带来了很大的挑战。
    • 分布式固有的复杂性:使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延迟、分布式事务等都会带来巨大的挑战。
    • 接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有使用了该接口的微服务都需要做调整。
    • 重复劳动:很多服务可能都会使用到相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这一功能,从而导致代码重复。尽管可以使用共享库来解决这个问题(例如可以将这个功能封装成公共组件,需要该功能的微服务引用该组件),但共享库在多语言环境下就不一定行得通了。

4、Serverless架构

  • Serverless(无服务器架构)是指服务端逻辑由开发者实现,运行在无状态的计算容器中,由事件触发,完全被第三方管理,其业务层面的状态则存储在数据库或其他介质中。
  • Serverless 是云原生技术发展的高级阶段,可以使开发者更聚焦在业务逻辑,而减少对基础设施的关注。
  • Serverless分为以下两个领域:
    • BaaS(Backend as a Service)后端即服务;一个个API调用后端或已经实现好的程序逻辑,这些API可以使用Baas提供的服务(如数据存储)。
    • FaaS(Functions as a Service)函数即服务,FaaS是无服务器计算的一种形式,当前使用最广泛的是AWS的Lambada。
  • Serverless架构能够让开发者在构建应用的过程中无需关注计算资源的获取和运维,由平台来按需分配计算资源并保证应用执行的SLA(服务等级协议),按照调用次数进行计费,有效的节省应用成本。其优点如下所示:
    • 低运营成本
    • 简化设备运维
    • 提升可维护性
    • 更快的开发速度
  • Serverless架构的缺点:
    • 厂商平台绑定,对平台依赖非常高,不能随便迁移或迁移成本很高
    • 目前成功案例比较少,没有行业标准。

四、大前端的组件化和模块化

1、概述

  • 移动互联网时代,大前端(前端和移动端)是和用户直接打交道的,其体验直接决定产品的生命力,他们是业务的重要载体;
  • 在早期,绝大部分App or 网站都是单工程 + MVC 架构;但是随着一些超级App出现,单工程 + MVC 架构已经难以满足这些App的需要了(超级App有微信、支付宝、淘宝、抖音等)
  • 于是乎,大前端软件架构朝着组件化和模块化方向发展;两者的核心思想都是:分而治之,将一个庞大的软件系统拆分成多个组件(模块);

2、组件化 & 模块化的区别

  • 组件化是基于可重用的目的,将一个大的软件系统按照分离关注点的形式,拆分成多个独立的组件,主要目的就是解耦,把系统拆分成多个组件,分离组件边界和责任,便于独立升级和维护。

  • 一个独立的组件可以是一个Native SDK or Web服务;这样独立出来的组件可以单独维护和升级而不会影响到其他的组件

  • 模块化是将一个程序按照其功能做拆分,分成相互独立的模块,以便于每个模块只包含与其功能相关的内容,模块之间通过接口调用。将一个大的系统模块化之后,每个模块都可以被高度复用

  • 模块化的目的是为了重用,模块化后可以方便重复使用和插拨到不同的平台,不同的业务逻辑过程中。

3、模块化 & 组件化带来变化

  • 团队划分:不同业务团队负责不用的业务,维护不同的组件,而这些组件可以组成一个超级App
  • 职责分离:不同的团队有不同的职责,有的负责业务A、有的负责业务B,有的负责性能....,这些职责分担了超级App在迭代、演进过程中遇到的问题和风险。
  • 技术选型灵活:不同的组件中,具体的技术选型可以根据团队实际来确定,比如不同的组件内部可以灵活选择MVVM、MVC软件架构。

五、几点思考

1、业务 VS 技术

  • 业务决定技术的上限:技术是为了解决业务问题的,业务能带来真正的价值,技术才有存在的意义。如果没有双11秒杀活动、春节抢火车票这些事情,流量削峰、削峰填谷这类技术就没有存在的意义。在一个业务高歌猛进的同时,技术也在不断演化;
  • 技术是业务的护城河:没有技术或技术无法支撑业务的快速迭代、快速试错,再美好的业务终究是水中月、镜中花,一纸空谈而已;
  • 技术和业务是相互促进的,相互依存。对于技术人来说,选择一个好的业务,对技术成长非常重要;业务中成长远快于从书本中学习,甚至是碾压。
  • 业务中经常会遇到棘手问题,一般需要先深度分析问题产生的原因,然后考虑技术方案,在设计方案时,需要评估复杂度、技术成熟度,是够有成功经验可借鉴,人员技术栈熟悉程度等;最后,在新方案落地时候,最好先做MVP(Minimum Viable Product,最小可用产品),灰度一部分看看效果。

2、个人 VS 团队

  • 有一定规模的互联网公司,团队职责都会细分,绝大数人在团队中只是做着或负责很小的一部分事情(俗称拧螺丝),但是职责划分是趋势,是团队进化的必然选择;
  • 在一个团队中,做什么很重要;但是更重要的是能看到什么;团队给你提供了一个非常大的平台,可以做的事情有很多,可以是技术,可以是沟通...
  • 团队中的个体通力合作,共同完成团队目标,不仅提高了个人的影响力,也提高了团队整体的竞争力。

3、技术人的边界

  • 而今,技术方向细分,每个技术人都在自己的方向深挖,这是非常必要的,因为这样才能组成一个全栈式、精益求精的团队,但是这还远远不够;
  • 技术人应该不设置边界(不是说没有边界):技术人应该跳出自己的领域,观察其他人、其他技术团队,甚至业务团队在做什么;主动去了解这条业务线上不同角色的职责,然后完善或扩张自己的边界;
  • 从当今的技术发展趋势来看,每个团队负责"小型"服务,"小型"服务内完成闭环,对外提供服务能力。而"小型"服务内的技术选型,技术栈是灵活的,甚至可以实现在"小型"服务内 技术 + 业务闭环。

4、技术专家 VS 架构师

  • 技术专家追求的是深度,需要专注于某些领域,某一类技术,需要对这方面了解非常透彻,适合做技术专家的领域有:安全、搜索、应用程序框架、缓存、JVM、分布式、RPC框架等,或更加底层的数据库开发,Web服务器开发, 编译器开发等。

  • 架构师追求的是广度,对深度并没有极致要求, 你可能并不了解一个系统的内部细节实现,但是一定要知道这个系统的特点、能力、性能和适用范围;在工作中,由点及面, 着眼系统整体和业务的全局,培养出设计系统架构的能力,把需求转化成合适的技术方案,然后推动方案的落地。

  • 根据自己的优劣势选择合适的方向,然后刻意练习,不断完善这方面的能力。

参考文章