小型系统如何“微服务”开发

懂点代码的大叔 2018-10-15 16:13:56 ⋅ 829 阅读

提到“微服务”,我相信网上各种“微服务”的演变案例都会给人一种“因大而分”的前提错觉,这可能会导致许多的“小白”产生没有机会接触“大项目”而对“微服务”可望而不可及也。当然,这种错觉的产生可能更多来源自于各种“微技术”的“层出不穷”所以“眼花缭乱”,例如Spring Cloud。虽然“大项目”机会不多,但也阻止不了“钉子们”通过教程把微技术跑一遍来装饰自己可以“微”起来的自信。

“微”只是一种正常思维逻辑

 想当年,入行如赶集,同样作为小白,能把SSH框架跑一遍竟然能给自己带来无比强大的工作自信。谁没个“资本”年龄,只可惜自身的“浮躁”逼退了当年追求“本质”的淡定和沉稳。在网互联网崭露头角的年代,系统的焦点可能不在于“单体”应用的“横向分布”,更多在于对整体业务的“竖向分层”。无论横分还是竖分,“分”的本质其实就是因为“重”。“分而治之”应该算是人类最基本的思维逻辑。只不过“分”的具体实现还得归咎于站在我们对立面的是什么问题。互联网是把“业务”从线下往线上迁移的主要推力,在这个互联网初始发展阶段,需要体现的可能是线上业务的完整性,因此业务的厚度成为了瓶颈,所以对业务逻辑层次的垂直划分可能是当时的关键解。随着移动互联网的普及,“线上业务”已经成为主流,业务的“厚重”已经积累到了另外一种层次,单纯的“竖向分层”已经无法满足厚重业务的积累和支撑。业务横向分解成为了突破口。大量“分布式”方案油然而生,包括“微服务”。从许多“大而微”的初始现象来看,确实很容易把“大”和“微”联系在一起,这也是“大”企业走在时代前沿面对“不确定性机会”所“创造”的现象。历史可以很轻易地给人一种“知其所行”的大局视野,但时代演员却很容易被局限当前。我个人觉得“微服务”的本质就是一种正常的思维,是一种基本解决问题的思路。“微服务”并非新招式,跟二十六种常用面向对象设计模式一样,随着时代经验的积累会成为我们解决问题的“基准招式”。因此也可以大概推测,未来的发展离不开“微服务”思维模式的导向,例如项目或组织的管理模式都可能会发生变化,或者说已经在悄悄地改变。如果说“微服务”确实像我分析的是一种思维模式,那就不会有大项目和小项目之分了。

“微服务”模式小案例

 在工作过程中,大项目毕竟少数,小项目才是考验技术人“接地气”的表现所在。有一天,我接到了一个小规模的“话费充值系统”需求,没有太多复杂功能和逻辑的描述,就是一个能让用户在上面自助充值的系统。剩下的理解,靠的就是自身工作经验的功力了。面对这样的需求,我首先想到的就是这个关键业务流程:

这个流程说简单可以简单,说复杂可以“媲美”电商系统,例如“充值金额”相当于商品,“充值”相当于购物,“订单”跑不掉,“充值话费”类比物流。各种电商该有的“边界问题”几乎都要考虑,规模虽小,但五脏都得要有。至于“五脏”有哪些,这得根据业务的边界范围去划分“业务领域”了,先来根据自己的经验尝试一把:

 

这种业务划分方式多少跟电商系统有点类似,直接呈现的是业务模型。根据“微服务”思维,每个领域都是一个独立的服务个体单元,每个服务“对象”又有自己的“属性”和“行为”:

每个服务的属性有“服务标识”、“服务名称”等,当然服务有自身的各种行为(更多以API体现),各种系统外部动作都是通过服务之间的“合作”来完成:

 

用户查看充值金额:接查询商品服务(“充值10元到账12元”,“充值100元到账106元”,......);

用户发起话费充值:订单服务接收请求→订单服务查询商品信息(商品ID)→订单服务向支付服务下支付订单→订单服务向充值服务下充值订单→订单服务自身下商品订单;

用户支付:支付网关(外围)接受请求→回调支付服务通知支付结果→支付服务更新支付订单状态→支付服务向充值服务发起充值→充值服务向充值网关(外围)发起充值并更改充值订单状态;

订单对账:定时支付网关对账、定时充值订单对账:

从以上流程可以看出,每个服务都有自己专注的“职能”,每个应用业务流程有需要1或N个服务的交互才能完成,每个服务都有自己独立的“数据源”,互不干扰。由于系统的初期规模预期比较小,可能每天就那么数百笔订单甚至可能更少,如果我们每个服务都需要“物理隔离”,未免有点大题小做。因此,项目初期我们按“单体”模式实施:

所谓的“单体”,即把所有服务代码结合一个“项目”打包发布,也就是一个“普通”的项目并且共用一个数据库,但每个服务的表名都有服务的标识(约定),例如商品服务的相关表名以“KWGOODSXXX”命名,订单服务的相关表名以“KWORDERXXX”命名,支付服务的相关表名以“KWPAYMENTXXX”命名,充值服务的相关表名以“KWRECHARGEXXX”命名,对账服务的相关表名以“KWACCOUNTXXX”命名,服务之间决不能跨越服务操作数据库表,必须按照“业务流程设计”调用,所以“单体”只是体现在物理实施层面,逻辑层面始终保持着“微服务”的分布式特性,保留了各种不用修改一行代码即可灵活扩展的可能性:

 

可能有人会问,“单体”模式的服务调用怎么调?“分布式”模式又是怎么调?怎么确保扩展时服务代码调用层面的不变?用的是什么技术?这篇随笔就先不谈太多的技术,服务的调用过程我大概通过伪代码图术一下:

 

服务之间协作的“透明化”关键在于把“微服务”灵活特性所导致的“变化”打包封装起来,就是以上伪代码的DiscoveryClient调用代理。DiscoveryClient在技术框架内维护了所有服务的信息(Service Data Cache Container),而服务信息的加载方式是服务解耦的关键所在。首先,框架通过本地扫描的方式把所有本地服务信息扫描并加载至“服务容器”(本地扫描LocalService)。其次,框架会检测本地的“服务信息”配置文件并加载至容器(静态解析)。最后,框架会根据配置前两步所加载的服务信息判断是否存在“发现中心服务”并动态地周期性向“发现中心”更新服务信息(动态解析)。因此,无论是单体应用部署还是分布式应用部署,对服务调用是透明的,保留了整个系统的灵活扩展性。到这里,整个系统的设计基本完,完整的系统架构图如下所示:

以上系统在无任何优惠的正常运行下,确实只能算得上小规模,一台服务器的单体部署模式足以支撑,但在每月会员日所推出“充100元送10元”商品的时候,单体应用就显得有点力力不从心了,商品服务访问量的增加(看得人多了)已经影响到了其它服务的稳定性,并且考虑对账的稳定性(以免充值不到账引起投诉),决定把商品服务和对账服务独立(进程)部署。通过加入网关(Nginx)进行服务分发(服务解耦):

在运营过程中,公司为了“流量经营”,不惜下血本推出“充100元送50元”的商品,系统再一次受到严峻的考验,为了业务质量,不得不把所有服务独立(进程)部署,增加支撑力度:

不知道是不是老板喝多了还是运营短路了,竟然提个“充值100元送100元”的商品,并明天上线,系统峰值支撑并发量的预测已经超出了我的想象力,我能做的只有这样了:

 

系统从业务规模来看确实存在大小之分,但从设计思想层面,系统是没有大小之分。以上“戏路”都是以服务为单元进行灵活扩展,其实业务的最小力度是服务的具体行为—API,每个API都是服务的一个独立行为,例如查询、变更等,完全符合“命令查询职责分离(CQRS)模式”的设计,按服务这种API粒度进行横向分解同样可行,例如“支付服务”存在支付订单查询API、支付订单下单API、支付结果通知接收API,我们可以通过读写特性把查询API和变更类API进行分离,同样可以以面向“消费对象”的角度进行分解:

如果某些业务存在服务链复杂的话(例如商品订单),还可以自定义“编排服务”解耦“基础服务”的复杂度:

总结

 如果细心点可以从以上案例发现,我的整个项目开发过程跟传统的可能会有点区别,什么区别呢?这里没有突出太多的实体对象设计或者表结构设计,更没有突出所谓的“三层结构”设计,而是直接从业务角度触发划分“业务对象”,而我们的服务呈现的是根据业务领域划分的“对象”描述,与传统按“数据实体”划分的设计模式还是有一定的区别,从需求设计到软件设计和开发都是“业务模型”最原始和最直观的呈现,保证了业务准确性并减少了变更的风险成本,同还大大地降低了项目的沟通成本。这种思想有一个更加专业的术语叫“领域驱动设计”。我深知自己距离所谓的“微服务”或者“领域驱动设计”还有一大段距离,并且以上案例还可能存在诸多的细节问题,但这种类似的思想确实是我自身从业务中摸爬滚打并逐步思考和沉淀而形成的设计习惯。不是别人说什么就做什么,而是通过实践去思考和领悟并向真正的源头的“大师们”学习。

往期精彩文章


如何找到完美的以太坊区块链开发者

大数据推荐系统实时架构和离线架构

ElasticSearch优化会员列表搜索

Rabbitmq延迟队列实现定时任务

软件做异常测试?必知的22个测试点总结!

Java SQL注入危害这么大,该如何来防止呢?

还没用上 JDK 11吧,JDK 12 早期访问构建版使用

Dubbo 整合 Pinpoint 做分布式服务请求跟踪


---------------END----------------

后续的内容同样精彩

长按关注“IT实战联盟”哦


全部评论: 0

    我有话说:

    「转载」服务分布式架构中,如何实现日志链路跟踪?

    背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用ELK来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,我们来看下面的图     上图

    你的老板逼你上服务了吗?

    “ 这些年软件的设计规模越来越庞大,业务需求也越来越复杂,针对系统的性能、高吞吐率、高稳定性、高扩展等特性提出了更高的要求。   图片来自 Pexels可以说业务需求是软件架构能力的

    开源资讯】JWCloud 专业版 v1.0.0 发布,基于 SpringCloud 研发的服务框架

    简介 JavaWeb_Cloud 服务平台是一款基于 SpringCloud 框架研发的分布式微服务框架,主要使用技术栈包括: SpringCloud、Vue、ElementUI

    「轻阅读」Dubbo 如何成为连接异构服务体系的最佳服务开发框架

    要实现异构服务体系间的共存或迁移,关键点在打通异构体系间的协议与服务发现,得益于 Dubbo 自身对多协议、多注册模型的支持

    开源资讯」大型服务系统管理工具,Istio 了解下

    Istio 是一个由谷歌、IBM 与 Lyft 共同开发开源项目,旨在提供一种统一化的服务连接、安全保障、管理与监控方式。

    商城系统 DBShop V3.0 Beta 发布

    全新重构,首次亮相。 系统简介 DBShop企业级商城系统,使用PHP语言基于Laminas(Zendframework 3) + Doctrine 2 组合框架开发完成。可定制、多终端、多场景、多

    信小程序实战篇:如何解决https域名问题 ?

    开发自己的信小程序绕不开https问题,为了能在小程序中调用我们自己的API服务请打开看一看吧!!!

    字节跳动 | 服务架构中如何优雅地重试?

    背景 在服务架构中,一个大系统被拆分成多个小服务,小服务之间大量 RPC 调用,经常可能因为网络抖动等原因导致 RPC 调用失败,这时候使用重试机制可以提高请求的最终成功率,减少故障影响,让系统

    Istio 1.8.3 发布,大型服务系统管理工具

    Istio 1.8.3 已发布,Istio 是一个由谷歌、IBM 与 Lyft 共同开发开源项目,旨在提供一种统一化的服务连接、安全保障、管理与监控方式。具体来说,Istio 是一个开源服务网格

    Fizz Gateway 1.1.1 发布,基于 Java异步框架WebFlux开发服务网

    Fizz Gateway 是一个基于 Java异步框架WebFlux开发服务网关,能够实现热服务编排、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理等目的,拥有强大的自定义

    什么是服务?什么是中台?阿里的中台战略?

    服务架构将单体应用,按照业务领域拆分为多个高内聚低耦合的小型服务

    SpringBlade v2.8.0 已经发布,SaaS 服务开发平台

    SpringBlade服务开发平台 采用前后端分离的模式,前端开源两个框架:Sword (基于 React、Ant Design)、Saber (基于 Vue、Element

    DDD 服务落地实战

    PS:让我们把DDD的思想真正落地,从数据库设计到代码实战演练,从电商、在线订餐 到智慧医疗全方位展示如何运用DDD 在服务+人工智能、嵌入式+物联网的项目中进行业务建模、系统规划与设计实践。

    开源资讯】cppweb 1.0.2 发布,基于 C++ 开发的 Web 服务器

    cppweb是一个基于C++开发的 WEB 服务器,支持C/C++、Python、Java等多语言混合开发WEB应用。 cppweb同时也是一个跨平台的服务开发框架,通过两个核心组件

    WebMIS 1.0.0 beta.3 发布,全栈开发基础框架

    全栈开发基础框架,包括 PHP / Python / SpringBoot / Phalcon / Flutter / NodeJS / Vue / Swoole / Redis / API 等技术

    Malagu v1.4.1 发布 - 支持 Serverless 优先的服务框架

    Malagu 框架简介 Malagu 基于 TypeScript 的 Serverless First、组件化、平台无关的渐进式应用框架。 背景 当我们着手开发一个新项目的时候,单体和服务架构该

    微型Java开发框架Solon 1.1发布,QPS达10万+

    简介 Solon 是一个微型的Java开发框架。项目从2018年启动以来,参考过大量前人作品;历时两年,2700多次的commit;内核保持0.1m的身材,超高的Web跑分,良好的使用体验

    打造千万级流量秒杀系统

    讲师:易乐天 前小米国际电商技术负责人 10 年软件开发经验。多年 Linux 系统编程、高性能和高并发编程经验。参与过亿级用户、千万日活、百万并发系统开发,曾经将 IM 云 WebSocket