微服务架构的前世今生(三):微服务设计原则
大家好,今天给大家带来是哈喽沃德先生的《微服务架构的前世今生》,上一篇用2个故事向大家说明了SOA 与微服务的区别。今天给大家带来微服务的设计原则。
一共有以下四个原则。
一、AKF 拆分原则
业界对于可扩展的系统架构设计有一个朴素的理念,就是:通过加机器可以解决容量和可用性问题(如果一台不行就两台)。
用个段子描述就是:世界上没有什么事是一顿烧烤解决不了的,如果有,那就两顿。
《The Art of Scalability》一书提出了一个系统的可扩展模型——AKF 可扩展立方。这个立方体中沿着三个坐标轴设置分别为 X,Y,Z。
一个叫 AKF 的公司的技术专家抽象总结的应用扩展的三个维度。理论上按照这三个扩展模式,可以将一个单体系统,进行无限扩展。
1、X 轴
X 轴扩展指的是水平复制,通过绝对平等地复制服务与数据,以解决容量和可用性的问题。很好理解,就是将单体系统多运行几个实例,成为集群加负载均衡的模式。
2、Z 轴
Z 轴扩展通常是指基于请求者或用户独特的需求,进行系统划分,并使得划分出来的子系统是相互隔离但又是完整的。以生产手机的工厂来举例:苹果公司为了发展在中国的业务,或者利用中国的廉价劳动力,在中国建立一个完整的子工厂,与美国工厂一样,负责完整的手机生产。这就是一种 Z 轴扩展。
场景说明:比如单体打车应用,一个集群撑不住时,分了多个集群,后来用户激增还是不够用,经过分析发现是乘客和车主访问量很大,就将打车应用拆成了三个,分别为乘客服务、车主服务、支付服务。三个服务的业务特点各不相同,独立维护,各自都可以再次按需扩展。我们可以水平扩展三个服务,形成各自服务的集群模式。实在不行最后根据北上广热门地区划分为多份,你在哪个城市打车,就给你展示哪个城市的司机数据分区。
二、前后端分离原则
以前的 Java Web 项目大多都是程序员既当爹又当妈,既搞前端,又搞后端。随着时代的发展,渐渐的许多大中小公司开始把前后端的界限分的越来越明确,前端工程师只管前端的事情,后端工程师只管后端的事情。正所谓术业有专攻,大中型公司需要专业人才,小公司需要全才,但是对于个人职业发展来说,前后端需要分离,毕竟一个人如果什么都会,那么他可能什么都不精。
1、未分离
在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。
这种应用模式比较适合纯网页应用,但是当后端对接 App 时,App 可能并不需要后端返回一个 HTML 网页,而仅仅是数据本身,所以后端原本返回网页的接口不再适用于前端 App 应用,为了对接 App 后端还需再开发一套接口。
该时期代表:Servlet + Jsp + JavaBean
<body> <% request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); System.out.print(username); %> </body>
2、半分离
前后端半分离,前端负责开发页面,通过接口(Ajax)获取数据,采用 Dom 操作对页面进行数据绑定,最终是由前端把页面渲染出来。步骤如下:
- 打开 WEB,加载基本资源,如 CSS,JS 等;
- 发起一个 Ajax 请求再到服务端请求数据,同时展示 Loading;
- 得到 Json 格式的数据后再根据逻辑选择模板渲染出 DOM 字符串;
- 将 DOM 字符串插入页面中渲染出 DOM 结构;
然而,在这种架构下,还是存在明显的弊端的。最明显的有如下几点:
- JS 存在大量冗余,在业务复杂的情况下,页面的渲染部分的代码,非常复杂;
- 在 Json 返回的数据量比较大的情况下,渲染的十分缓慢,会出现页面卡顿的情况;
- 资源消耗严重,在业务复杂的情况下,一个页面可能要发起多次 HTTP 请求才能将页面渲染完毕。PC 端建立多次 HTTP 请求也没啥。这里需要考虑一下移动端的感受。
该时期代表:SSM(Spring + SpringMVC + Mybatis)和 SSH(Spring + Struts2 + Hibernate)
3、分离
在前后端分离的应用模式中,后端仅返回前端所需的数据,不再渲染 HTML 页面,不再控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App 有 App 的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。
浏览器不再直接请求 JSP 的 API,而是:
- 浏览器请求服务器端的 NodeJS;
- NodeJS 再发起 HTTP 去请求后端;
- 后端依然原样 API 输出 JSON 给 NodeJS;
- NodeJS 收到 JSON 后再渲染出 HTML 页面;
- NodeJS 直接将 HTML 页面 flush 到浏览器;
这样,浏览器得到的就是普通的 HTML 页面,而不用再发 Ajax 去请求服务器了。
该时期代表:VueJS、AngularJS、ReactJS
4、总结
从经典的 Servlet + Jsp + JavaBean 的 MVC 时代,到 SSM(Spring + SpringMVC + Mybatis)和 SSH(Spring + Struts2 + Hibernate)的 Java 框架时代,再到前端框架(VueJS、AngularJS、ReactJS)为主的 MVVM 时代,然后是 Nodejs 引领的全栈时代,技术和架构一直都在进步。创新之路不会止步,无论是前后端分离模式还是其他模式,都是为了更方便地解决需求,但它们都只是一个“中转站”。前端项目与后端项目是两个项目,放在两个不同的服务器,需要独立部署,两个不同的工程,两个不同的代码库,不同的开发人员。前端只需要关注页面的样式与动态数据的解析及渲染,而后端专注于具体业务逻辑。
- 前后端技术分离,可以由各自的专家来对各自的领域进行优化,这样前端的用户体验优化效果更好。
- 前后端分离模式下,前后端交互界面更清晰,就剩下了接口模型,后端的接口简洁明了,更容易维护。
- 前端多渠道集成场景更容易实现,后端服务无需变更,采用统一的数据和模型,可以支持多个前端:例如:微信 h5 前端、PC 前端、安卓前端、IOS 前端。
三、无状态服务
对于无状态服务,首先说一下什么是状态:如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。进而依赖这个“状态”数据的服务被称为有状态服务,反之称为无状态服务。
这个无状态服务原则并不是说在微服务架构里就不允许存在状态,表达的真实意思是要把有状态的业务服务改变为无状态的计算类服务,那么状态数据也就相应的迁移到对应的“有状态数据服务”中。
场景说明:例如我们以前在本地内存中建立的数据缓存、Session 缓存,到现在的微服务架构中就应该把这些数据迁移到分布式缓存中存储,让业务服务变成一个无状态的计算节点。迁移后,就可以做到按需动态伸缩,微服务应用在运行时动态增删节点,就不再需要考虑缓存数据如何同步的问题。
也就是对同一个 url 请求没有上下文关系。举个生活中的例子:
比如空调遥控器,你按上下调整温度时,空调温度设定值会变化,遥控器信号到空调是单向传输。现在空调显示温度 20 度,遥控器 20 度。如果遥控器与空调之间是有状态的,假设你离开空调接收范围调整了遥控器温度,变成 19,那回到范围内你按一次升高一度,基于原先温度状态,遥控器给空调发送一个“提高1度”的指令,就会出现遥控器提高到 20,而空调变成21。如果要空间与空调之前是无状态的,假设你离开空调接收范围调整了遥控器温度,变成 19,那回到范围内你按一次升高一度,遥控器给空调发送一个“设定温度值20”,这样两者最终还是相同的值。
四、Restful 通信风格
基于**“无状态通信原则”**,在这里我们直接推荐一个实践优选的 Restful 通信风格 ,因为他有很多好处:
- 无状态协议 HTTP,具备先天优势,扩展能力很强。例如需要安全加密时,有现成的成熟方案 HTTPS 可用。
- JSON 报文序列化,轻量简单,人与机器均可读,学习成本低,搜索引擎友好。
- 语言无关,各大热门语言都提供成熟的 Restful API 框架,相对其他的一些 RPC 框架生态更完善。
今天先就讲到这里,下一篇将会讲述:CAP 原则与 BASE 理论 。点击获取java微服务spring全家桶视频教程资料,全面深入学习微服务架构师课程。