本文首发于公众号:托尼学长,立个写 1024 篇原创技术面试文章的flag,欢迎过来视察监督~
小张本科毕业后就入职了一家电商公司,目前已经在这工作了两年。
最近公司想要发展跨境电商业务,于是技术总监让小张、老陈和另一个小同事从国内的电商项目组中抽出来,再重新搭建一个跨境电商平台。
老陈沉思了一下,说:“咱们要不这样,海外电商就别用微服务架构进行开发了吧,改为使用单体架构进行开发。”
小张有些疑惑地问:“为什么不跟现在的国内电商平台保持一致,也使用微服务架构进行开发呢,微服务架构才是主流趋势啊,单体架构据说全是缺点。”
老陈神秘地笑了笑,说:“咱们国内电商平台以前也是单体架构,微服务架构是一个大厂架构师来了之后搞的,说是为了公司业务发展和系统演进。
至于这个跨境电商平台,咱们就重新搞回单体架构吧,慢慢你就明白有多爽了。”
小张将信将疑地点了点头。
CQRS ——> 多表关联
没过多久,小张就感受到了第一个爽点。
公司的客服团队提了需求,希望实现对订单的多维复杂查询功能,查询项但不限于:下单时间、支付时间、订单状态、订单的商品品类、下单用户手机号等,并且需要支持分页和排序。
如果换做以前的微服务架构,需要通过CQRS模式进行实现才行。
也就是将用户服务、订单服务和商品服务的业务数据,通过Canal同步到ElasticSearch中形成大宽表,来支持对订单的多维复杂查询功能。
如下图所示:
而现在的单体架构就简单多了,小张直接在MyBatis中将订单表、商品表和用户表进行多表关联,where条件中列出查询项,再通过limit和order by支持分页和排序即可,一条SQL语句搞定一切。
分布式事务——>本地事务
马上小张又感受到了第二个爽点。
那就是在实现下单扣减库存逻辑的时候,他再也不用引入Seata来实现分布式事务了。
况且如果选择场景适合且性能最高的TCC模式的话,他还得自己手写代码来实现Try 阶段和Confirm / Cancel 阶段的业务逻辑, 那真是麻烦到家了。
1、Try 阶段
如上图描述,Try 阶段所做的事情是,对各个业务服务进行业务检查和资源预留,并返回结果。
2、Confirm / Cancel 阶段
如上图描述,Confirm / Cancel 阶段则是根据 Try 阶段执行的结果,进行业务提交或业务回滚操作。
嗯,单体架构是不需要对数据库进行拆分的,小张这个在createOrder()方法中加上Spring的@Transaction注解,一行代码解决战斗。
服务化调用——>本地调用
小张感受到的第三个爽点在于,终于从服务化调用变成本地调用了,这里面省了太多的工作。
在微服务架构中,如果选择OpenFeign进行RPC调用,还的需要一个注册中心进行服务注册发现,并在服务调用者段引入各个依赖jar包。
对了,还得设置各种超时时间、重试次数之类的参数。
写好了一段代码逻辑之后,如果需要做联调和单元测试的话,各个同事还得将上下游的各个服务全部启动起来,看看能不能互相调通之类的。
嗯,使用单体架构就容易得多了,直接在代码里进行本地方法调用,一行代码、不到一分钟轻松搞定。
DevOps流程系统上线后,小张终于感受到了他的最大爽点,那就是在整体的DevOps上,那真的是轻松得一批。
1、在微服务架构中,业务代码开发完成后进行提测,需要合并本次修改的好几个工程的代码,并将其部署到测试环境中,错一个差一个都会有问题。
2、在微服务架构中,一坨微服务的测试环境维护起来真的麻烦,不知道哪个服务的代码没有更新到最新版本,测试起来都会遇到问题。
3、在微服务架构中,测试完成进行发布上线的时候,需要发布好几个服务才行,还要梳理清楚这些服务的上下游依赖,不然在发布上线期间会出现故障。对了,上线发布失败进行回滚的时候也同样麻烦。
4、在微服务架构中,问题排查也着实让人头疼,想查清楚一笔下单为什么耗时这么久,还得引入链路追踪工具SkyWalking或者Spring Cloud Sleuth + Zipkin。
同样,想查清楚一笔下单为什么报错,还得引入EFK日志收集、排查工具,麻烦得要死。而单机架构统统没有这些问题,提交代码只需要Merge一个工程的代码,发布上线也只需要发布一个工程,SkyWalking、Spring Cloud Sleuth + Zipkin、EFK都不需要,只要有一个Prometheus + Grafana监控工具即可。
至于只有一个服务的测试环境,那维护起来更不是事儿了。
结语
当然,我们在这里绝不是要抹黑或全盘否定微服务架构,毕竟存在即合理。只是三五个人的小研发团队真没必要引入,更没必要过度微服务化,在服务粒度上拆分得过细,仅此而已。