技术开发者该如何开展小团队的微服务之路

中科白癜风医院 https://mjbk.familydoctor.com.cn/bjbdfyy_video/

作者

王鼎

责编

刘静

微服务是否适合小团队是个见仁见智的问题。回归现象看本质,随着业务复杂度的提高,单体应用越来越庞大,就好像一个类的代码行越来越多,分而治之,切成多个类应该是更好的解决方法,所以一个庞大的单体应用分出多个小应用也更符合这种分治的思想。当然微服务架构不应该是一个小团队一开始就该考虑的问题,而是慢慢演化的结果,谨慎过度设计尤为重要。

公司的背景是提供SaaS服务,对于大客户也会有定制开发以及私有化部署。经过2年不到的时间,技术架构经历了从单体到微服务再到容器化的过程。

单体应用时代

早期开发只有两个人,考虑微服务之类的都是多余。不过由于受前公司影响,最初就决定了前后端分离的路线,因为不需要考虑SEO的问题,索性就做成了SPA单页应用。多说一句,前后端分离也不一定就不能服务端渲染,例如电商系统或者一些匿名即可访问的系统,加一层薄薄的View层,无论是php还是用Thymeleaf都是不错的选择。

部署架构上,我们使用Nginx代理前端HTML资源,在接收请求时根据路径反向代理到server的端口实现业务。

接口定义

接口按照标准的Restful来定义,

版本,统一跟在/api/后面,例如/api/v2;以资源为中心,使用复数表述,例如/api/contacts,也可以嵌套,如/api/groups/1/contacts/;url中尽量不使用动词,实践中发现做到这一点真的比较难,每个研发人员的思路不一致,起的名字也千奇百怪,都需要在代码Review中覆盖;动作支持,POST/PUT/DELELE/GET,这里有一个坑,PUT和PATCH都是更新,但是PUT是全量更新而PATCH是部分更新,前者如果传入的字段是空(未传也视为空)那么也会被更新到数据库中。目前我们虽然是使用PUT但是忽略空字段和未传字段,本质上是一种部分更新,这也带来了一些问题,比如确有置空的业务需要特殊处理;接口通过swagger生成文档供前端同事使用。持续集成(CI)

团队初始成员之前都有在大团队共事的经历,所以对于质量管控和流程管理都有一些共同的要求。因此在开发之初就引入了集成测试的体系,可以直接开发针对接口的测试用例,统一执行并计算覆盖率。

一般来说代码自动执行的都是单元测试(UnitTest),我们之所以叫集成测试是因为测试用例是针对API的,并且包含了数据库的读写,MQ的操作等等,除了外部服务的依赖基本都是符合真实生产场景,相当于把Jmeter的事情直接在Java层面做掉了。这在开发初期为我们提供了非常大的便利性。但值得注意的是,由于数据库以及其他资源的引入,数据准备以及数据清理时要考虑的问题就会更多,例如如何控制并行任务之间的测试数据互不影响等等。

为了让这一套流程可以自动化的运作起来,引入Jenkins也是理所当然的事情了。

开发人员提交代码进入gerrit中,Jenkins被触发开始编译代码并执行集成测试,完成后生成测试报告,测试通过再由reviewer进行代码review。在单体应用时代这样的CI架构已经足够好用,由于有集成测试的覆盖,在保持API兼容性的前提下进行代码重构都会变得更有信心。

微服务时代

服务拆分原则

从数据层面看,最简单的方式就是看数据库的表之间是否有比较少的关联。例如最容易分离的一般来说都是用户管理模块。如果从领域驱动设计(DDD)看,其实一个服务就是一个或几个相关联的领域模型,通过少量数据冗余划清服务边界。单个服务内通过领域服务完成多个领域对象协作。当然DDD比较复杂,要求领域对象设计上是充血模型而非贫血模型。从实践角度讲,充血模型对于大部分开发人员来说难度非常高,什么代码应该属于行为,什么属于领域服务,很多时候非常考验人员水平。

服务拆分是一个大工程,往往需要几个对业务以及数据最熟悉的人一起讨论,甚至要考虑到团队结构,最终的效果是服务边界清晰,没有环形依赖和避免双向依赖。

框架选择

由于之前的单体服务使用的是springboot,所以框架自然而的选择了springcloud。其实个人认为微服务框架不应该限制技术与语言,但生产实践中发现无论dubbo还是springcloud都具有侵入性,我们在将nodejs应用融入springcloud体系时就发现了许多问题。也许未来的servicemesh才是更合理的发展道路。

这是典型的SpringCloud的使用方法,该图取自纯洁的微笑


转载请注明:http://www.aierlanlan.com/tzrz/4968.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了