上海网站开发薪资,网站建设公司怎么拉单,搜索引擎官网,php网站建设工程师作者 | 张羽辰#xff08;同昭#xff09;阿里云交付专家 导读#xff1a;如今#xff0c;几乎所有的事情都离不开软件#xff0c;当你开车时#xff0c;脚踩上油门#xff0c;实际上是车载计算机通过力度感应等计算输出功率#xff0c;最终来控制油门#xff0c;你从…
作者 | 张羽辰同昭阿里云交付专家 导读如今几乎所有的事情都离不开软件当你开车时脚踩上油门实际上是车载计算机通过力度感应等计算输出功率最终来控制油门你从未想过这会是某个工程师的代码。 当我们谈论架构时我们到底在谈论什么
面向对象编程函数式模块化设计微服务这些词汇貌似都和架构这个 buzzword 有点关系的确我们这个领域充满了很多难以理解的词汇这些词汇从英语翻译到中文已经丧失了部分上下文再随着上下文的改变使得意义彻底扭曲比如引擎、框架、架构、应用、系统……诚然大家都或多或少对这些词语达成共识在工作中使用这些词汇进行沟通某时就是指“我们都懂的那个东西”但是在我深入的想聊聊架构或者说软件架构时的确不得不问自己这个问题我们到底是谈论什么
事实上架构这个词根据上下文所确定的范围较为固定建筑学上的架构指代房屋结构、整体设计、组合构成等而这些 high-level 设计往往并不需要全面了解底层就像使用 RestTemplate 进行 WebService 调用时我们也不关心 socket 是在四层连接的一样因为细节被隐藏了。
但是建筑学上的架构与软件架构却又极大的不同之处问题出现在“软件”这个词上按照 software 的词解ware 是指产品一样的东西而 soft 则强调易变这是与 hardware 所对应的。我们希望“软件”能够进行快速的修改应该能够快速响应甲方或者客户的需求所以软件架构必然不像建筑架构一样建筑一经建成修改的成本极高而软件应该走对应的方向发挥易于修改的特点。 “现在的大多数软件非常像埃及金字塔在彼此之间堆建了成千上万的砖块缺乏结构完整性只是靠蛮力和成千上万的奴隶完成。” —— Alan Kay。 笔者认为虽然这句话表达的意思我很赞同但实际上金字塔作为帝王的陵墓是有着完整的设计逻辑并且随着好几座金字塔的迭代的以及逐渐完备的施工管理后期金字塔是非常杰出的建筑代表并作为地球上最高的人造建筑持续了好几千年。关于金字塔是否由奴隶建造还是存有争议。图片来自 Isabella Jusková Unsplash。 作为工程师我们一方面关注软件产品的能力和行为这往往是一个项目的起点另一方面我们需要关注软件的架构设计因为我们希望设计有着弹性、易于维护、高性能、高可用的系统更希望系统能够不断演进而不是在未来被推倒重做。所以回正我们的视野当我们决心要设计一个好的架构时我们需要明确架构往往决定的是软件的非功能性需求。这些非功能性需求有
易于开发我们希望工程师一进入团队就可以立刻开始进行研发工作我们希望代码易于阅读与理解同时开发环境足够简单统一说到这里大家可以回想下当你进入项目时学习上下文的痛苦。当我们开始采用 docker 辅助开发时时任架构师提出了一个要求只要一行命令就可以使用 docker 启动本地测试环境而且必须所有的微服务都要做到这一点。痛苦的改造完成后三年后进入项目的同学只需要安装好 docker再在 ternimal 中运行一句 ./run-dev.sh 就能够获取一个具有完整依赖的本地环境提效明显。方便部署如果系统的部署成本很高那使用价值就不会很高了我们很多企业都存在那种动也不敢动改也不敢改停也不敢停的系统除了祈祷它别挂掉好像没有别的办法或者很多企业都采用了 K8s 这种先进的编排系统但是在应用部署和上线时还是走的每周四变更的路子。现代的发布方式 AB、金丝雀、灰度无法采用是因为改造成本过高或者没有足够的自动化测试来保证改动安全更别提将发布做到 CICD 里面了。易于运维DevOps 的初衷是建立一种缩短运维与研发距离的文化让出现问题后更容易处理希望让大家将视野放在产品上而不是限定自己的工种这并不是期望运维的同学能够成为 Java 专家迅速的进行 heap 分析发现问题我们强调的是运维时的闭环能力。在软件产品层面我们也希望产品是足够独立的、自治可以独立部署能够做到横向扩展有着完整的可观测性毕竟当今的硬件成本很多时候是远远小于人力的。维护成本随着时间的推移给软件增加新功能就会变的越来越难越是运行长久的项目就会陷入重写还是重构的苦恼。往往风险在与修改代码会增加破坏已有功能的风险而且技术债也会越来越多难以偿还即使是重写某些功能和模块我们也很难确定是否真的覆盖到了所有的功能简而言之dont break anything 的确很难做到。以及最重要的一点演进能力良好的架构设计应该能让系统处于易于演进的状态能够实现给飞驰的汽车换轮胎的能力而不会被框架、底层的某种数据库、操作系统或者其他东西所绑架但是这太难以做到了。的确在项目进行技术选型时因为某种数据库的特性而有倾向但是在上层设计中我们必须保证不依赖于数据库的特性而将使用这些特性的地方放到底层细节中。我们也需要考虑不使用 Spring 提供的 Dependency Injection我们该如何组织我们的 beans也要考虑将来系统的前端是 web 还是 mobile 还是都要支持
这里引用 Robert C·MartinUncle Bob的原语“软件产品是有两方面的价值一方面是实现功能的价值另一方面是架构的价值而架构的价值可能更重要一些因为它代表着软件 soft 的特性。” 本书例子过少而且缺乏现有流行框架的重构或者改进建议有点形而上但是在方法论层面笔者还是认为值得一读。Robert C·Martin 对数据库特指 RDBMS的态度很值得讨论首先他认为数据库是一种细节在架构中应该与业务解耦他强调业务代码与数据库的无关性。同时在我们的代码进行计算时表格往往不是理想的数据结构比如有些场景会使用树、DAG 等等。可以回想一下当你需要把一个树存入数据库时你该如何实现 微服务是一种软件架构不要扩展它
根据我们之前的讨论后端系统采用微服务是不会影响到其功能上的价值本质上微服务化和单体应用的差别并不会表达在功能上很多微服务进展不顺利的同学会经常说到这东西用单体写早就完事儿的确是这样这侧面也印证了微服务只是一种软件架构而不是别的神奇的东西并不是某个业务需求必须要使用微服务完成我们看中微服务也是看中了架构方面的优势即那些非功能性需求。也有人使用 pattern 来描述它也有人说和 SOA 基本上是一个东西只是粒度不同所以我们一开始就别相信这个世界有灵丹妙药也别期望有个什么技术能够瞬间替代 Oracle。
作为开发“企业级后端应用”的同学我们经常会面临很多非业务需求上的苦恼有时我们需要同时支持移动端、移动 web、桌面端三种客户端有时候我们需要支持不同的协议比如 JSON 或 XML有时我们又需要使用不同的中间件传递消息或者在研发时我们知道有一个地方写的不好我们想在未来补课重构我们想尝试最新的技术但是代价过高系统无法扩容或者成本极高系统过于复杂无法在本地运行导致极低的效率……这些苦恼才是采用微服务的主要驱动力回到我们对软件架构的讨论之中我们希望的是通过足够松耦合的独立服务来降低组件之间变化的成本也就是说今天更新发送通知的功能并不会影响到用户查看购物车也不会让研发人员半天改完再等三天才能上线。
但是世界上没有免费的午餐虽然我们知道微服务有很多很好的特性比如组件即服务、松耦合、独立部署、面向业务、高维护性、高扩展性等等这里并不想展开讨论它的好处我们先考虑投入成本。假设我们每个同学都完整的学习了微服务的所有知识对市面上的框架、产品非常熟悉摩拳擦掌准备开始在拆解完几个服务后我们会发现没有足够的自动化手段靠手动的方式进行测试、编译、部署、监控这是显而易见的会降低体验如果没有优化好的部署策略所有的服务都在某个发布日上线那更是一种灾难。 随着规模的扩大单体应用的代码改动成本会越来越大。很多时候我们微服务的架构实践是存在误区的我们总认为流量经过某个 gateway 后直达某个服务确忽视了服务之间调用的场景理想的微服务架构应该是一张网每个节点都是独立的、自治的服务。 一些之前使用单体很容易做到的场景在分布式的环境下会更加困难。比如我们可以通过 RDBMS 提供的数据库事务来支撑一致性但是如果订单服务和价格服务分离势必要进行分布式事务来保证一致性往往是最终一致性而分布式事务的成本和难度就不用赘述了。在单体环境下我们可以很轻松的使用切面进行权限验证而在微服务的场景中服务之间相互调用是难以控制的。
拆分服务或者服务边界划分是另一件很难做到的事情最吃香的理论也许是根据 DDD 去进行划分天然的领域或者子域domain貌似都能对应一个服务因为足够的界限上下文bounded context能够保持服务的独立性使其细节被隐藏在界限之内听起来是个不错的主意。但是现实却十分残酷使用 DDD 生搬硬套去进行软件开发的例子不在少数成功例子也难以复制。
虽然我在实践中也经常使用业务领域去进行服务划分但是我并不认为这是 DDD 的做法没有必要规定有多少个 domain 就有多少服务也不需要规定 sub domain 能否独立服务。与其进行顶层设计一揽子的解决方案我更相信演进的力量如果你真的需要拆分一个服务足够的基础设施与自动化工具应该允许你低成本的去做而不是一开始就画好所有的架构图。这就跟所有的改革一样革命派往往不是一步功成而是逐渐的积累的。所以使用微服务当你能够负担的起only you can afford it)也表示你能负担的失败一样技术世界不存在一蹴而就all in 非常危险。
卫报网站Guardian的微服务改造就是一个很好的例子网站核心依旧是一个巨大的单体但是新功能通过微服务实现这些微服务调用单体所提供的 API 来完成功能。对于常常出现的市场活动比如某个体育比赛的专用板块这种方式能够快速实现活动页面与功能完成业务需求并在活动结束后删除或丢弃。我之前参与项目中也通过等量替换与重构慢慢绞杀Strangler Pattern掉一个巨大的陈旧的 JBoss 应用。
PlayStation 首席设计师 Mark Cerny 在今年的 PS5 新主机的技术分享中提到游戏主机需要平衡好演进与革命balance the evolution and revolution我们不想丢掉多年来开发者的积累在复用过去的成功经验时我们也希望大家能够使用更先进的技术。
人人都爱恨 Spring Cloud
看起来在 Java 世界中Spring Cloud 貌似是微服务的最优解了甚至在很多同学的简历上Spring Cloud 几乎可以和微服务划等号了不止一次的有人告诉我说公司的技术栈不是 Java所以搞不了微服务很难受并不是我没有学习精神和冒险精神云云。很遗憾对于软件架构来说跟可没有规定编程语言设计模式不是也出了很多版本吗归根结底还是 Spring Cloud 的全家桶策略更吸引人什么事儿都不如加上几个 jar 就能拥有的神奇次时代架构更有吸引力。
不可否认我在学习 Spring Cloud 的时候也惊叹其完整性几乎常见的微服务需求都有足够完整的解决方案而大多数方案是做在应用层具有良好的适配性比如 eurake 的注册发现、zuul 网关与路由、config service、hystrix circuit breaker 等等通过统一的编程范式基于 annotation 的注入与配置足够丰富的功能选择常用功能甚至都有两种选择以及较好的集成方式。前有 Netflix 的成功经历后随着微服务的浪潮再加上足够庞大的 Java 社区可以说是王道中的王道。但并非 Spring Cloud 没有弱点反倒这些功能设计与随后的容器化浪潮产生了分歧至今融合 Spring Cloud 与 Kubernetes 都是热门话题这里我们展开说说它的不足或者限制limitation。
侵入性与语言绑架
这可能是最大的问题基本只能使用 Java 作为研发语言这一点在国内也备受争议因为不论是作为架构师还是入门的程序员都需要尝试新的技术栈来进行储备或是采用新的功能而且比如使用自制的 client 去实现 ribbon 的负载均衡也是很难的但是如果不用 Java做到这一点也很难不是说 Java 语言不够优秀而是我们对未来应该有更多的选择对于一个技术公司来说编程语言应该不会成为限制试问这个时代谁不想学习一点 golang 或者 rust 或者 scala 呢其他服务比如 SSO、Config Service 也过于整体如果想进行某项适配则必须进行大量的修改还好是开源的。我们很担心这种情况都会随着框架的老去而面临推到重来的境界Ruby on Rails 可能就是前车之鉴吧。侵入性是另一个问题还记得我们在讨论软件架构时所提倡的实践规则吗尽量不要让顶层设计依赖底层的框架或者某种细节但是满屏幕的 annotation 与 jar 的直接引用无疑告诉我们想去掉它们还是非常难的。
云原生的融合问题
对于云原生不论是 CNCF 还是 Pivotal VMWare都在强调容器化、微服务、面向云环境等CNCF 围绕 Kubernetes 开始发展壮大也随着这种先进的容器编排技术的流行人们渐渐发现它和 Spring Cloud 在功能上还是存在很多重叠虽然 k8s 与 IaaS 没有重叠但是现在还有多少厂商再推纯 IaaS 呢既然有功能重叠就有取舍考虑到 Spring Cloud 的全家桶属性这个分歧处理一直都不能很好的解决。 集中式的资源
不论是 Config 、Eureka 都是聚合的单点及时它们有集群的方式达到近乎 100% 的可靠性但在逻辑架构上所有的微服务都依赖它们这些集中式的资源的耦合是非常强的它们会一直存在在你的生产环境之中直到最后一个使用它们的系统下线。我们在架构中需要避免使用共享的实例与资源一个应用不会因为不能写日志而崩溃也不应该因为本地没有 eureka 而无法启动。
畏惧平台绑定
诚然在进程之内解决服务注册发现、负载均衡是很好的它代表了最好了平台无关性但平台的其他能力也很难享受的到了。绑定 k8s 貌似是个更好的选择因为相对于 Spring Cloud 它更灵活也能做到不会被基础的云平台绑定但也更难以掌握与运维。当然我也不是认为 K8s 必须作为微服务的选择作为容器的编排平台它可以做更多的事情比如跑数据库、中间件等运行微服务应用只是其中之一。
方法论的落地能力
2020年已经过了一半从技术上来说Serverless 已经进入成熟期Kubernetes 也更加成熟已经成为事实的标准。但是很多时候我们的方法论与架构设计是跟不上的技术发展的很多同学可能还在经历每周的发布日很多同学还没办法改进团队内老旧的技术很多同学的 Jenkins 还是停留在打包的阶段很多同学机器上还是没有安装 docker很多时候并不是框架或者平台的问题而是方法论还停留在过去。
保持演进
应用程序也应该践行开闭原则对扩展开放使得我们在未来有更多的选择。微服务是一个很好的机会能让我们真正的演进架构而不需要付出过多的代价当我们需要组件化系统时组件的关键特性正是可独立替换或升级我们可以不影响其他部分去进行替换和重构这样的成本是显然低于抛弃旧的巨型框架而重写的。有着正确的态度和工具我们可以更快、更频繁的控制变更我们可以激进的选择新的技术栈也可以合并两个耦合过紧的服务随着服务的不断聚合、抽出你会发现系统的逻辑架构会越来越清楚再进行修改就会信心倍增了。我们可以针对每个服务使用不同的存储技术我们可以使用 OSS 处理文件而不是继续往 Oracle 里面塞图片和视频。
Istio 的解法与问题以及 Mesh 还缺少什么 这个开幕雷击虽然槽点满满但并没有降低社区对 Istio 的信心反倒是渐渐发现这次的大改动使 Istio 变得有点好用了可以在生产中采用而不需要付出太多代价了。当然漂亮话永远好说。 2017 年的时候 Service Mesh 还是一个襁褓中的概念现在已经成为了微服务领域的未来之选但遗憾的是目前只有 Istio 足够成熟能代表这项技术当然我也有幸实践过类似的 Sidecar 来进行反向代理、日志收集、性能监控、健康检查等功能但是距离 Mesh 的愿景还是有大的差距。
今天并不想展开 Service Mesh 或者 Istio 的优势进程之外的解决方案能够确保系统的灵活性而流量控制、服务治理、端对端的传输安全、限流、发现注册等等我们希望工程师能够聚焦业务实现架构的灵活性聚焦真正的价值而剩下的进行配置就好。所以我想这也是 Serverless 被无限看好的原因既然我们想 delegate 对基础设施的控制那为什么还需要关心容器呢Istio k8s 的方案已经足够好至少我们团队正在认真学习在向客户提供最佳实践之前我们依旧有很多问题需要解决下面列出一些代表性的
弹性与自恢复问题
使用系统度量、参数等触发弹性伸缩是常见的需求这里我们是使用云监控还是自己搭一套我一直倾向数据与用途解耦使用 pub sub 模式解决问题比如 CPU 过高可能会触发多个行为触发警报触发弹性规则展示在 dashboard 上。我们可以增加 pod 来分担服务的压力或者因为某个 pod 异常退出后启动新的 pod 来完成自恢复这系列动作也是需要我们自己解决的。
监控与可观测性
日志、警报等可观测性的问题这一方面的实践较多唯一比较担心的是 ARMS 或者 Newrelic 这种 APM 功能目前没在目标平台上实践过我们希望能够清晰的看到每个服务的实时性能目前这一部分还缺乏考虑与设计。
限流与降级的实践
Istio 的流量控制能力是非常强大的如何对服务采取降级、限流这种常见的治理操作也是需要总结出实践经验的。避免串流错误cascade failure在微服务领域也很常见也需要避免故障蔓延。
多种自动化部署
蓝绿、灰度、金丝雀这些多样的部署方式也需要落地我们可能会写一些 deployment util 之类的小脚本部署的方式需要和 CICD 打通。一个部署工具一个配置文件一个 CICD 组成未来单个应用的部署方式。
ABAC 与 OPA
基于属性的权限控制以及 OPA 的可定制性我们是非常看好的而且 sidecar 可以在进程之外解决权限验证问题的确值得尝试刚好也学习下 golang 用于定制 OPA。
Saga 与补偿事件
分布式事务是微服务实践中的大坑我曾经也写过类似的文章项目经验中更多的是将事务放在单一的服务内再加上我自己也没机会写过真正的网店系统。补偿事件也是常用的最终一致性方案总之放在一起验证。
高可用和混沌工程
基于 K8s 实现应用的高可用应该不难容器的天生优势就是易于启动与管理如果随机杀掉 pod 不会影响系统可用性这就算是实现了类似于 SLB ECS ASG 的能力真正危险的是其他 非业务型 pod比如 istio 的各种 supervisor。 实践微服务作为架构师所考虑的东西远远大于只是实现业务但是一旦铺平道路下来的研发与迭代将会更加顺利。 后记
如果你也对云原生架构有浓厚的兴趣欢迎 加入钉钉交流群 与我们交流
推荐下载
《深入浅出 Kubernetes》一书共汇集 12 篇技术文章帮助你一次搞懂 6 个核心原理吃透基础理论一次学会 6 个典型问题的华丽操作
关注阿里巴巴云原生公众号回复 排查 即可下载电子书
参考资料
https://martinfowler.com/articles/microservices.htmlhttps://medium.com/swlh/stop-you-dont-need-microservices-dc732d70b3e0https://medium.com/capital-one-tech/10-microservices-best-practices-for-the-optimal-architecture-design-capital-one-de16abf2a232https://www.geekgirlauthority.com/what-you-need-to-know-from-sonys-the-road-to-the-ps5/https://dev.to/bosepchuk/why-i-cant-recommend-clean-architecture-by-robert-c-martin-ofdhttps://istio.io/latest/blog/2020/tradewinds-2020/https://www.openpolicyagent.org/docs/latest/
作者简介
张羽辰同昭阿里云交付专家阿有着近十年研发经验是一名软件工程师、架构师、咨询师从 2016 年开始采用容器化、微服务、Serverless 等技术进行云时代的应用开发。同时也关注在分布式应用中的安全治理问题整理《微服务安全手册》对数据、应用、身份安全都有一定得研究。 “阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践做最懂云原生开发者的公众号。” 原文链接
本文为云栖社区原创内容未经允许不得转载。