🗂 目录

我理解的架构 & 架构师(兼谈微服务)

October 6, 2018 • 预计阅读时间 13 分钟

一个好的架构师离不开三个核心东西:问题,技术,人

不同的架构师

types-of-technology-architects

💬 软件开发是以最终产品为导向的,所以本质上我倾向把自己当作软件工程师或者系统架构师,软件产品的制造者和拥有者。下面的内容比较杂。

我理解的架构和架构师

从事商业性的系统开发超过二十年了,经手的 mission critical 系统最少也有十几,二十个,对自己最擅长的方面做个总结。

  • 架构 architecture 来源于建筑行业,架构就是 blueprint 实施蓝图。软件架构的实质还是软件,也就是代码 ⏤ 架构师自己如何编码,只是没有全部亲自写出来。对于复杂系统,架构应该是系统设计之上更高级的抽象,我认为的架构,系统设计,代码应该是同源的,划分代码,组织代码,运行代码,支撑代码,等等,都是以代码为核心。

所谓架构和系统设计,其本质都是代码设计,也就是架构师给出的代码结构,脱离代码的架构都是耍流氓,脱离业务的代码也是耍流氓

  • 系统设计和软件如何编码一样,范围很广,基础理论杂,主要还是来源于实践经验,里面的很多设计决定和哲学相关。所以不仅仅是懂怎么做的,更多是体会为什么要这么设计所以原则很重要。架构和系统的本质还是编程,系统级别的编程,所以编程的一些经典原则也非常适用:

    • DRY:Don’t repeat yourself
      系统设计中你碰到的问题别人都已经碰到过了,向高手学习他们的解题方法。另外,别重复别人的错误,对于设计和架构,不止学技术,懂得来龙去脉非常重要。

    • KISS:Keep it simple, stupid!
      我更喜欢解读成 Keep it stupid, so it can be simple(笨方法往往是最好的方法)。

    • Avoid Creating a YAGNI:You aren’t going to need it
      类似 MVP(Minimum Viable Product)- 极简原则,可造可不造 ⏤ 别造, 可用可不用 ⏤ 别用,不知道怎么做 ⏤ 先研究,这在设计 API 时非常有用,同样可以应用在系统设计上。

    • Abstraction Principle

    • Minimize Coupling
      解耦原则:复杂问题的解决方法来源解耦,解的过程就是深入认识问题的过程 ⏤ 如果代码的力量来源抽象,那么系统的威力就来源于解耦,这是两根大棒,但不要“滥用”(💡 抽象和解耦都是有代价的),得不断提高这方面的能力

    • Separation of Concerns

    • Single Responsibility Principle

    • Maximize Cohesion
      像搭积木一样,解决问题和写代码时尽量采用组合或延续的办法而不是从头开始,复用的威力

    • Open/Closed Principle
      完整性和灵活性是架构师和优秀程序猿时常考虑的问题,也是 NB 或菜鸟的区别所在

    • Don’t make me think
      把问题讲清楚,问题已经解决一大半了

    • Principle of least astonishment
      一切和想的一样,no news is good news

    • Avoid Premature Optimization

还有其它的一些提法,如 SOLID 原则,不过我更喜欢/倾向从代码角度看待架构:

solid

系统设计更多的是艺术而不是科学,优良的系统设计遵循编程的原则和模式

  • 复杂系统的设计是需要有技术手段做支撑的,架构师本身必须是个很好的程序员,具备相当的“深度”与“宽度”。所以架构师必须爱好学习,持续不断的学习,持续编码,保持对最优秀技术的敏感度,才能设计出真正优秀的架构。和其它事物一样,学习、思考、实践 ⏤ 学习好的系统设计,思考后面的思想,实际中应用和解决问题,是提高架构水平的唯一方法。

复杂系统的设计是需要有具体核心技术做支撑

  • 面对的是复杂系统的设计,通常没有固定的对错答案和所谓的 silver bullet。一个优秀架构师的成长需要经验积累,这和通常单项技术被动学习有所不同。一个优秀架构师最重要的能力是分析和抓住复杂事物的本质。例如五代战机的特点就是 4S - 隐身性能、超音速巡航、高机动型和超视距打击,五代战机的设计核心就是回答如何实现 4S。架构师最重要的能力还来源于深度思考,学习的不只是技术本身,还思考技术的来龙去脉,前因后果,思考解决问题的方法论 ⏤ 也就是套路,不断归纳和总结。

系统设计具有非常强烈的问题驱动,架构师自我思考和实践的特点,必须能够回答系统的核心问题是什么,解决的关键是什么

  • 通常程序员只是一个人在编码,向组长负责。而架构师需要面对不同的 staleholder,带领一大群人编码完成项目,需要很好工程能力以及跨领域的知识。 一个优秀的架构师对系统设计考虑的问题必须非常全面,内部的,外部的,看得到的,看不到的,现在的,将来的,例如新技术的成熟度,实施该模块团队的技术储备,用户体验,项目的资金和时限,承受风险的能力,等等。需求是软件开发的原动力,商业、客户、技术都是在变化的,而一个系统的开发大都需要 2,3 年,所以架构师必须对需求和商业有一定深度的理解和前瞻性,能够引领和超越客户、领导的提出需求,这些都影响架构的选型,扩展,冗余以及性能设计。越复杂的系统和商业需求越是考验一个架构师。除了专业知识,架构师还要有较好的软实力,如沟通技巧,组织管理能力,情绪控制能力,理解他人等。这些东西都是不能从书本直接得到,而需要经验的积累。

系统设计是一个架构师对技术,人,问题综合理解的体现

主要的架构模式

10 Architecture Patterns Used In Enterprise Software Development Today

更多可参考:

  微软文档:Application design patterns

  solution-architecture-patterns

分布式系统的学习

data-intensive-system
 此书有八百多个 Reference,所以也可以进一步细读。

💡 题外:系统偏向以命令/流程方式集成还是数据方式集成是个难点,很多架构师都没有想清楚,导致系统混乱不堪。

微服务是什么和为什么

4、5 年前就开始了所谓的微服务(Microservices),做过布道,做过大规模实施,下面以此为例,总结自己的思考和理解。

微服务是什么,众说纷纭,不过要说到名词解释,必须看 Martin 的 Microservices 介绍 :

the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.

可惜听起来还是不甚了了。

我总结微服务有 4 个核心/鲜明特点:

  • 设计解耦(design independently)/商业拆分:这里讲的架构不是技术架构,而是商业逻辑架构,这在大层面上决定了软件如何拆分,这可以应对商业需求在情况下不明确或者比较复杂下,先找出"基本解”。design independently 接下来的好处就是各部分的开发是可持续演化性(continuously evolutionary),而单体架构(monolithic),在商业不明确或比较复杂情况下,特别是创业公司,设计上无法完全确定下来,导致开发迟迟无法开动或完成;同时一个部分的变化会直接引发整体做出变化,这导致两种恶性后果,一是某一部分成为瓶颈拖累整体,另一个是开发后,大家都无法持续改进。例如典型的三层架构,很多表,很多代码都是和自身负责的模块无关;一个小改动整个项目需要重新构建;某个底层库由于各个模块都依赖,到了一定时候,各个模块的视角不同,有的模块想改进这个库或采用完全新的技术,但动不了了,成为技术瓶颈或死结,所谓的 legacy,重构无望,这时候只有等更高层做决定,推倒重来。注意微服务不只是技术拆分,因为,代码技术上是可以做到随意拆分,而企业或商业运作是不能随意拆分的,拆分需要符合体制和流程,微服务的系统最终由人来运作,所以不是所有的项目都适用微服务架构。

  • 技术解耦(implement independently)/多元化技术:要体现微服务的最大威力一定是采用 polyglot,已有的软件解决方案可以直接采纳,管他是 javascript 还是 python 开发的,管他是自己开发还是他人已经提供的,也不管是通过 lib 或者还是 api。传统的 java 或 .net 包头包尾,一种数据库,一个通用数据层,要承担不同的技术考量,结果自然局部非最优解。技术解耦带来了技术革新,例如各种 nosql,而且在不同公司,不同项目中可实现重用,实现快速开发,宏观层面上发挥了最大效益:“Service Endpoint first instead of APIs”。所以微服务属于八仙过海各显神通,不再是单一的三层架构,从一层(如 serverless),到 n 层,都是可能的。

  • 资源解耦(sourcing independently)/游击队战术(coway rule & full stack developers):标准解释 ✓ 一个 service 团队的规模不超过两个 pizza。小团队才能带来快速灵活技术和快速迭代,“大象能跳舞”是个伪命题。要注意的是游击队战术不是适用所有的企业和商业模式,也不是所有的企业具备游击队的人员结构,所以微服务不是每个企业都适合的。

  • 部署&运行解耦(deploy&run independently)/自动化运维(devops):自动化运维(DevOps)不是微服务特有的,在现有的项目或系统上完全可以实施自动化运维,也可以看到巨大效益,CI/CD 在微服务提出之前已经存在了。但自动化运维是实施微服务的必备技术,拆分和 ployglot 后对自动化运维提出了很高的要求,一堆不同质的东西可以单独部署,升级,同时又要组合在一起无间隙运行。容器技术的出现,对微服务所要求的大规模自动化运维提供了必要的技术基础。

微服务的核心仍就是沿用“模块化”式思路设计整个系统,目的是达到软件的可重用和可扩展

names

纵观开发历史,微服务不是什么新东西,仍旧是代码的拆分和集成,和 component-based 或 SOA 是一致的,只是层面不同。微服务不是针对小型软件或者单个项目层面,因为大部分的软件项目还没有等到解耦,拆分,长期演化成为”硬“需求,项目已经结束或者死掉啦。但反之,不同技术实力的团队,不同的项目,不同的地点,不同的时间,重复开发和实现,微服务解耦特性就能把软件的最大价值发挥出来,否则都是在做 silo application/project。所以微服务在政府,大公司或大型项目中推广和应用才能发挥其威力。

另外,微服务还包含了开发团队的架构,运维的架构,这是和以往的纯系统架构概念非常不同的地方,也是实施微服务可能忽略的地方。微服务同时锁定了以 service 为导向的开发和运维模式(service oriented development and operation)。

抓住微服务以上四个特点和目的后,很多疑问就迎刃而解。

微服务的本质就是:分布式系统

微服务的技术栈

如果在 IT 界呆得够久,了解分布式一路走来的历程,就会明白“微服务”从技术讲没有什么特殊的新问题,只是技术手段的不断翻新,技术点包括:

microservices-stack

在我看来,注册,配置,数据一致性,链路跟踪,是微服务最基础和特有的技术点。

对应每个点都可以找到相应的具体技术,微服务的老大和先行者是 AWS,可惜它不开源。业界广泛的开源方案就是 Spring 系列的 Spring Boot & Spring Cloud,另一套是正在兴起是基于容器和 Kubernetes 的 服务网格(Service Mesh)。Spring Cloud 虽然是目前最成熟的方案,但从技术高度讲,我认为是开倒车或者说属于第一代的技术尝试(对比以前的 Corba,DCOM,J2EE,Web Services),不是发展大方向。

以 Cloud Native 为基础才是微服务的明天,但是目前火热的 service mesh 仍然不成熟,参考:   服务网格(Service Mesh )101

大规模微服务/分布式的坑

代码和工程的质量仍是软件的灵魂,拆分和集成并不意味着可重用/可扩展就是必然。相对 monolitch,微服务/分布式系统对技术/人其实提出了很高的要求。

如果你不能设计一个优良的单体系统,那么微服务也帮不上忙

  • 系统实施一致性:大规模的微服务实施往往变成一抓就死,一放就散,游击队战术的引入,各组人马自行乱搞,各种 style,违背了 KISS 和 DRY 的金典,引入更多更复杂的技术,反而使得整体性变得异常复杂,脆弱,低效和难以维护;

  • 商业从来不是 decouple/loosely coupled 的,系统集成依旧是所有复杂商业软件系统设计的难点和关键点,越复杂的系统越需要系统性的设计,微服务设计上往往倾向 decouple/loosely coupled 使系统设计难度陡增:

    • 一个好的 API 设计已经如此不易,想要设计优良的、对外的、可复用的 service 对大多数小团队其实是无法胜任;

    • 服务的拆分很容易变成 premature optimization(一开始时就拆分而不是系统成熟时或对系统有成熟认识时拆分),做着做着,Json 和 REST 会变得越来越臃肿,理论上可以各自演进,实际却极大可能从一坨屎变成一坨一坨的屎 💩💩💩;

    • Domain-Drive Design(DDD)从来都是个纸上的东西,正确的废话而已,拿来做服务拆分没有太大的帮助,没过几年又会拉出来炒一炒,因为那是个可以忽悠人的好东西 ⛔️;

    • 所有的微服务拆分之后还要合成一个有机的整体,系统控制和设计不会因为拆分而消失,反而因为拆分而在整体上大大增加数据和系统正确性的难度,统一的系统设计尤其重要,系统如何正确控制和响应各种 分布式系统之殇Fallacies of distributed computing )- 这方面绝大多数开发人员包括架构师都欠缺考虑或者没有很好的经验,经典的分布式设计或编码 8 种错误假设:

      • 网络是稳定的
      • 网络传输的延迟是零
      • 网络的带宽是无穷大
      • 网络是安全的
      • 网络的拓扑不会改变
      • 只有一个系统管理员
      • 传输数据的成本为零
      • 整个网络是同构的
  • 引入复杂的分布式技术导致滥用或不慎用:

    • 可读性下降、出错性上升:异步调用促使程序的碎片化,增加了流程处理和错误处理的复杂度,降低了程序可读性,响应速度,以及数据处理效率;
    • 性能下降:基于 Json 的 REST 还是序列/反序列 RPC 调用增加了数据的正确性和完整性判断,同时调用链急剧加长;
    • 采用微服务后,除了把变更数据记录在本地数据库外,还对外广播,同时无形把网络流量拉升若干个数量级,同时相同或类似的数据拷贝存在无数个拷贝和版本;
    • 并发问题:由此而导致奇怪问题次数大增,如网包或 message 丢失,同时 debug 变得比较困难
  • 异步计算挑战:分布式系统调用除 RPC 外就是消息系统支撑的 Event Driven Architecture ⏤ 异步是系统集成最主要也是最重要的手段,ESB(Enterprise Service Bus),Event Sourcing,CQRS,Streaming Processing,还有更隐晦的 Reactive Systems 等等,被推崇得像一粒粒银弹/迷魂弹,底层问题时如何确保消息的可靠性,顺序性;

  • 数据维护,一致性以及分布式事务,网上那个鼓吹很多的 saga pattern 也是出自那些 evangelist 或者所谓的 paper architect,用来解决实际数据一致性问题基本是不可行的 ⛔️;

  • 强大的基础设施,运维,监控,调试,恢复手段对微服务尤其重要,例如死信队列,流量重放,数据高可用,动态日志,容器化应用,蓝绿部署,等等

  • 除了这些直接的运维辅助手段,还有需要各种工具应对接口设计,编码质量,设计文档,项目多模块管理,测试等等

微服务的小结

  • 微服务不是新鲜事物,本质是分布式系统;
  • 微服务架构只覆盖了软件基础架构,系统设计依旧要在整体上回答如何统一完成各种商业需求;
  • DevOps 必须先行;
  • 复杂度加大,开发体验下降,对开发者要求提高;
  • 复杂系统不易,复杂系统的微服务实施必须谨慎,相当谨慎;

我的评论

Beyond Microservices: Streams, State and Scalability • Gwen Shapira • GOTO 2020

Seeing this pattern so many times - microservices and event-driven have values but overemphasising the goods and dumping traditional design around apis and db, the system “may” end up with much worse things - event schema vs. normalized db schema, bloated message vs. concise api, building on top of every single piece of event vs. building on top existing modules and functional apis, etc.

Microservices Architecture From A to Z :

Overall quite good article, I have 2 things to point out according to what I learn: 1. in principal SOA is same as Microservices, it was just focusing on integration of different systems, so it was not meant for reusability, scalability, ops agility like Microservices; 2. Choreography is a big mistake and most Microservices advocates go for it. The design of softare architecture is tended to be decoupled/distributed but business never be like that and the system design should be always united and integrated. Distributed logic (business or funcational) is just too complicated to get it right especially for a modern business. We all know No.1 rule is to avoid distributed computing. For common or supporting components/services, I will follow choreography pattern. But for core services belonging to the business process (e.g. in e-commerce: shopping cart, warehoursing, payment, accounting) I will stick with orchestration design. I have learned this through a few very big Microservices projects in different industrials.

Microservices Database Management Patterns and Principles

Unfortunately under the context - catalog, shopping cart, ordering, i think, the anti-pattern is the best solution. When in the ideal case to go for microservices, database-per-service is the best practice, the others are actually anti-patterns - its not practical to do that with a huge microservices system and I am strongly doubt those advocates have handson experience. CQRs, Event Sourcing, and Saga, are more like patching approach because the system has been designed as microservices when it is not necessary.

Why Agile Sucks for Building Quality Software

What you are saying is perfectly correct, but then what Agile brings on table specifically for building good software? Agile is not helpful because in reality it focus on the process instead of the meaningful techniques. Agile is more about methodologies and it can come in different forms. So i wont think it sucks but it does not help. Good developers/teams/architects are agile by quality.

99% 的软件项目都是被“复杂度”杀死的,而这是微服务/分布式系统的死结(参考经典文章:📃 How Complex Systems Fail )。

作为架构师,抛开各种技术和复杂表象,其工作核心就是: 对抗熵增(We want to fight entropy)

complexity

系统设计 & 架构microservices

  上一篇:Mac 的设置和软件 2018岁末版(2020.3更新)

  下一篇:Vagrant 小技巧

comments powered by Disqus