微服务是不是一种错误的方向?

166 天前
 Joker123456789

先说想法

这个标题并非一时兴起,也并非哗众取宠,而是我这段时间以来的思考。为什么会出现这样的想法?这还得从一个事实说起。

众所周知,微服务并不能提升整个项目的吞吐量,它的作用仅仅只是把项目按照一定的规则拆分成各种模块,然后每个模块都可以交给不同小组去开发。他解决的仅仅是大项目的团队协作问题。而真正能提升吞吐量的,除了程序本身的质量那就是负载均衡了,而且事实上微服务的架构中,每个服务都是以负载均衡的形式部署的,所以这里就有一个问题了:

如果仅仅是为了解决 [大项目的团队协作问题] 那么常规的模块化设计是不是也能做到?

现在由于 maven 的出现,再加上企业内部可以搭建私服,我们完全可以让每一个服务都以 jar 包的形式来开发。举个很简单的一个例子,比如有一个用户服务,订单服务,现在一般的做法是写一个聚合服务去调用这两个服务的接口,来实现业务逻辑的整合。

那如果把用户服务换成用户模块 jar 包、订单服务换成订单模块 jar 包,以 jar 包的形似传到私服,然后同样的写一个聚合服务,聚合服务把这两个 jar 包引入进来,是不是也能达到这样的效果?

如果需要负载均衡,那我们把这个聚合服务部署多个就好了,完全不影响。我完全想不到跟微服务比起来有什么坏处,如果有,欢迎大家指正。

微服务有什么缺点

  1. 耦合性太高,虽然开发和部署不会影响别的服务,但是你如果动了接口的出入参,那么其他服务就得同步升级了,而且是调用了这个接口的服务都要升级,又或者你需要为此单拎一个接口出来,做版本区分。
  2. 需要注册中心,项目会多出一个中间件,提升复杂度。
  3. 会消耗内网带宽,甚至是公网带宽,因为服务之间的调用都是通过网络完成的。
  4. 会出现分布式事务的问题,因为一个事务的操作可能会分布在不同的服务上执行。

如果用常规的模块化方案

  1. 虽然耦合也高,但是如果你动了接口的出入参甚至是接口名,别的服务是不需要立刻升级的,除非你是在改 bug ,但这是被业务逼着升级,因为不升级是有 bug 的,但他不会被技术逼得升级,因为模块只是被打成了一个 jar 包引入了其他模块里,无论你怎么变,已经部署在线上的别的模块里依然是用的你的老代码。
  2. 不需要注册中心
  3. 不会消耗多余的带宽资源
  4. 不需要分布式事务了

还是压力问题

一定会有人说,你把这么多模块都塞进一个服务里,那这个服务得部署多少台机器啊。

说到这里,就不得不从全局来看待问题了。我们可以看两张图(不好意思,有错别字,但是已经截图了就懒得改了,能看懂就行)

图 1

图 2

根据上面的两个图,我们是不是可以这么说,微服务在面对相同的流量时根本没有节约服务器的数量?反而还多了?

假如左边的聚合服务,他的业务量需要 10 台服务器才能支撑,右边的需要 5 台才能支撑,那么一共是 15 台。而微服务会导致 A 部署 15 台,B 也部署 15 台,再加上两个聚合服务,一共需要 32 台以上。

当然了,这只是极端的情况,现实中可能 A 服务不需要处理这么多业务,他可以少部署一点,又或者 B 服务可以少部署一点。但无论怎么算,服务器都是多了。

如果采用 jar 包的形式,那么只需要 15 台就够了,10 台用来部署左边的聚合服务,5 台用来部署右边的聚合服务。

说到底

这其实就是以三方库的思想在设计模块化,如果有一个工具类叫用户管理,有一个工具类叫支付管理。当你需要开发登录功能的时候,只需要引入一个 jar 包,然后调用里面的某个方法就好了,当你需要开发支付功能的时候也一样,你不需要去学习 dubbo ,不需要去学习 springcloud ,甚至不需要去关注注册中心是否挂没挂,注册中心的 url 是多少,服务到底有没有正常发布,有没有正常被发现。你会不会觉得这样有什么不妥呢?

以上只是个人的一点浅薄见解,欢迎大家理性探讨。

6582 次点击
所在节点    Java
50 条回复
dxddd
163 天前
“众所周知,微服务并不能提升整个项目的吞吐量”。你这第一段我就不赞同,微服务或者服务化刚开始就是为了提升吞吐量,虽然提升吞吐量,但是牺牲了一定效率并提升了成本。微服务比服务化更近一步的是更细粒度调节。一般程序的吞吐量瓶颈主要就在数据库,原本一个项目依赖一个数据库,现在依赖 100 个数据库(我说的极端些),吞吐量当然有提升。

你这里槽点有点多,不一一辩解了。还是那句话:“组织即架构”,适合自己组织的才是最好的架构。
heiya
163 天前
我浅显的理解是项目流量高且必须满足项目大、复杂这两个条件才可以上微服务,其余不用。
RandomJoke
163 天前
@Joker123456789 订单是核心服务了,你这个例子完全是在找极端,比如淘宝里打卡服务挂了重启,这个时候影响用户下单你觉得合适吗,核心业务核心服务可能成熟了,都不怎么动,只需要新业务部分不熟就可以了,再极端点,都在一个服务里,新上的功能导致 oom ,导致你核心业务全挂,那也不合适,所以本身微服务就是根据业务适度做就行了
ioufev
163 天前
最近搜索到了 OSGi ,说是:一个服务一个 Jar 包,在一个 JVM 上运行多个彼此隔离的 Jar 里的服务。再搜索相关库,基本在前几年就不更新了,Java 的模块化也从 Java 9 开始用 Java Platform Module System ,插件扩展形式也是基本的 SPI 方式,修改了配置需要重启 JVM ,而不是 OSGi 的热插拔。OSGi 提供服务注册和发现,和现在的微服务思想都是一致的。OSGi 的配置和管理相对较复杂,需要处理大量的模块、版本和依赖关系,对于大多数现代应用来说,这种复杂度是过于笨重的。
junwind
163 天前
我觉得微服务还是不错的,看你怎么用,一个大服务器,分成 n 个小服务,各自对外提供服务 api ,部署灵活,维护简单,团队人员也灵活,总之,看自己的业务量,业务量单一的,可以不拆分,但是业务繁杂的,建议分开,并不是非要用流行的微服务那一套架设,就按系统分为一个一个的单体服务就行。
charleslin
163 天前
完全赞同这个观点,为了微服务而微服务
pocketz
161 天前
你图裂了,掘金不让外站访问
Joker123456789
150 天前
@dxddd 有没有一种可能,单体也可以分库分表?所以你用这个举例子显然是不合理的。
dxddd
149 天前
@Joker123456789 你这么一说到还真是。一个工程,A 模块访问 A 库,B 模块访问 B 库,C 模块访问 C 库。技术上确实可以,不过我在现实里确实没见过了。
CodeCaster
149 天前
看完这个问题以及上面所有的讨论,我想提出一种全新的思路,大家可以一起讨论下。

首先,在微服务出现以前,大多数服务是以单体应用的形式存在的,后续由于各种原因(项目变大,需求变多等等)演变为微服务。单体应用有单体应用的优点与缺点,微服务也有微服务的优点和缺点。这两种模式的争论其实一直存在,正如 @micean 说的,“从一个极端到另一个极端”,这句话一点不错。我觉得其实是有解决方案的,是不是可以在这两个“极端”中找一个平衡点呢?

记得 2023 年的时候,google 开源了一款软件,叫 service weaver ,他有一个口号,“以单体形式编码,以微服务形式部署”,他的这个思路非常新颖,主要想告诉大家的一点就是,编码的时候可以按照一个模块一个模块来开发,互相没有耦合,但是最终部署的时候可以选择是单体应用一起部署,或者是微服务分开部署。

其实,我们团队在这之前也一直在做这方面的探索,但是一直没有开源,直到 2025 年春节前,我们的项目也开源了,我们以 Java 为主,推出了一套插件化的开发框架,每一个模块都可以以插件进行开发,插件之间互相不感知,但是我们参考 OSGI 的思想(@ioufev ),做到了插件可以聚合成一个进程部署(单体应用形态),或者分开部署(微服务形态)。

如果做到了这一步,是不是可以解决楼主的问题呢?其实微服务并不是一个错误的方向,而是在技术的螺旋式上升演进过程中的一个关键点。

以下是我在知乎上回答的类似问题的回答: https://www.zhihu.com/question/11654944781/answer/96580243167
这个是我们这个插件化框架的社区地址: https://github.com/ModelEngine-Group/fit-framework

我们项目刚开源不久,欢迎来讨论单体应用和微服务之间的相关问题,如果有同学们喜欢,也可以给我们点个 Star ,鼓励一下我们,感谢~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1113366

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX