Hanggi
V2EX  ›  程序员

目前哪种服务端架构模式最优?

By Hanggi at 2020 年 4 月 21 日 · 7525 次点击

传统服务端项目都是使用一种分层架构模式(这里用 MCV 举例):

.
├── Model
│   ├── Model_A
│   ├── Model_B
│   └── Model_C
├── Controller
│   ├── Controller_A
│   ├── Controller_B
│   └── Controller_C
└── View
    ├── View_A
    ├── View_B
    └── View_C

这种架构方式会有很多变种,但是大体结构相似,就是相同层级的文件会放在同一目录里。

最近,越来越多的项目使用一种以功能为边界的架构模式:

.
├── A
│   ├── Model
│   ├── Controller
│   └── View
├── B
│   ├── Model
│   ├── Controller
│   └── View
└── C
    ├── Model
    ├── Controller
    └── View

有种说法说这种架构模式方便日后微服务化。

如果主要以开发效率、维护成本、可扩展性等,这些核心需求来考虑,哪种架构模式更好更具发展性呢?

58 条回复  •  2020-04-22 20:02:28 +08:00
lhx2008
   1
lhx2008  
   2020 年 4 月 21 日 via Android
有啥区别,只是文件夹不同而已。。
hantsy
   2
hantsy  
   2020 年 4 月 21 日
小项目用 1 就可以了。

大一点的项目必须用 2 结构,不同的 Domain 分开,也方便以后拆分。
ben1024
   3
ben1024  
   2020 年 4 月 21 日
看迭代和人力交互
1.迭代速度快,人力交互略差,扩展性略差
2.迭代速度慢,人力交互方便,内部通信成本增加,扩展性好
hantsy
   4
hantsy  
   2020 年 4 月 21 日
1 。不同的 Domain 之前, 一些本来有 Entity 耦合的情况,使用 ContextMapping 概念,用一些 Ref 代替
2 。Domain 之间调用切换到 Message Broker,或者 REST API 等。
Hanggi
   5
Hanggi  
OP
   2020 年 4 月 21 日
@lhx2008
怎么说呢,感觉主要是依赖方式不同。

1. 的话是一种网状依赖,相互之间的依赖关系不明确。
而 2. 会把重度依赖的放一起,轻度依赖的分开来。

不知道这么说对不对。
huijiewei
   6
huijiewei  
   2020 年 4 月 21 日
用结构 2 吧

小项目就打包成一个
大项目就分开打包

更加灵活
gemini767
   7
gemini767  
   2020 年 4 月 21 日
个人认为没啥区别,团队统一好了

大应用拆应用
opengps
   8
opengps  
   2020 年 4 月 21 日
小系统选 1,大系统选 2,2 可以轻松的吧每一个业务板块单独拆出来
janda
   9
janda  
   2020 年 4 月 21 日
第二种挺像 微服务中这样的的了!每个都是完全独立的
kaiser1992
   10
kaiser1992  
   2020 年 4 月 21 日
DDD ?
Hanggi
   11
Hanggi  
OP
   2020 年 4 月 21 日 via iPhone
@janda 实际操作中很难做到完全独立,比如 A 里的一个表跟 B 里的一个表有一对多的关系。那就会有一条依赖从 A 伸进 B 。
这种情况,一般怎么处理呢,到时候要拆的时候怎么拆呢?
index90
   12
index90  
   2020 年 4 月 21 日
感觉没有区别啊
Hanggi
   13
Hanggi  
OP
   2020 年 4 月 21 日 via iPhone
@index90 一种区别是,
1 。开发的时候你要在多个文件夹里跳来跳去,特别是文件数量超多的时候,会很烦。
2 。的话,所有相关联文件可能都在附近。
rioshikelong121
   14
rioshikelong121  
   2020 年 4 月 21 日
前端也是这样的吧。小项目第一种,比较大的项目第二种。
index90
   15
index90  
   2020 年 4 月 21 日
@Hanggi 所以为什么你不分成多个 repo,而要堆在一起?
xcstream
   16
xcstream  
   2020 年 4 月 21 日
混合 A 和 B 的模式
Hanggi
   17
Hanggi  
OP
   2020 年 4 月 21 日 via iPhone
@index90 一个项目啊,比如 A 是用户模块,B 是文章模块,C 是视频模块,类似这么分,同一个项目怎么可能分在不同的 repo 呢。
lower
   18
lower  
   2020 年 4 月 21 日   ❤️ 2
把两者结合一下:D


├── A
│ ├── Model
│ │ ├──Model_A1
│ │ ├──Model_A2
│ │ └──Model_A3
│ ├── Controller
│ │ ├──Controller_A1
│ │ ├──Controller_A2
│ │ └──Controller_A3
│ └── View
│ ├──View_A1
│ ├──View_A2
│ └──View_A3
├── B
│ ├── Model
│ │ ├──Model_B1
│ │ ├──Model_B2
│ │ └──Model_B3
│ ├── Controller
│ │ ├──Controller_B1
│ │ ├──Controller_B2
│ │ └──Controller_B3
│ └── View
│ ├──View_B1
│ ├──View_B2
│ └──View_B3
└── C
├── Model
├── Controller
└── View
noobsheldon
   19
noobsheldon  
   2020 年 4 月 21 日   ❤️ 1
@lower 这不就是 Django 的结构吗
Kirsk
   20
Kirsk  
   2020 年 4 月 21 日
从 service 开始按模块分
看业务有可能分两层 service
底下就是作为基础层 model
其实用 API 服务化的思维去做服务端我觉得比较合适
view 已经弱化了
这么分的理由是业务共性的东西会逐渐下沉形成比较稳定的层级或功能,service 层之上根据业务来
huijiewei
   21
huijiewei  
   2020 年 4 月 21 日
@Hanggi 项目不大就把所有模块集中到一起,项目大了考虑分离就去除依赖,使用 RPC 或者微服务
wangyzj
   22
wangyzj  
   2020 年 4 月 21 日
“服务端架构模式”??????
wizardoz
   23
wizardoz  
   2020 年 4 月 21 日
我只想说第一种很无脑
hello321
   24
hello321  
   2020 年 4 月 21 日
果断第二种
janda
   25
janda  
   2020 年 4 月 21 日
@Hanggi 这样每个项目之间进行通讯、需要一个注册中心、把多个集中在一起!这样就相当于 N 个模块、变成一个项目了!不过这样操作成本比较大、维护也比较麻烦的!大项目用这种比较好、小项目用你的 A 方法就行了
siganushka
   26
siganushka  
   2020 年 4 月 21 日
Symfony Bundles 了解一下
mitu9527
   27
mitu9527  
   2020 年 4 月 21 日
哪里有什么最优解决方案,只有最合适的解决方案。选择适合当下的方案,然后当需求变化时,改成适合新需求的方案。
Hanggi
   28
Hanggi  
OP
   2020 年 4 月 21 日
@mitu9527 但是项目都是从小规模做起,到最后变多大往往也是无法预计的,到时候再重构不是成本更高吗?
Samuelcc
   29
Samuelcc  
   2020 年 4 月 21 日 via Android
个人喜欢第二种,通过 package private 的方式解耦各个模块,不会互相耦合,方便拆分和重构,也适合按照功能查找代码。
mitu9527
   30
mitu9527  
   2020 年 4 月 21 日
@Hanggi 就因为没办法预计,才应该选择最适合当下的。别人的也不见得适合你,就拿微服务来说吧,真正适合的公司就没多少家,服务数量都没上来就开始准备拆分,明显考虑的太早了。Keep It Simple 。
xuanbg
   31
xuanbg  
   2020 年 4 月 21 日
无脑选 2 就行。第一种非常容易写着写着就不清不楚地黏糊在一起了
abcbuzhiming
   32
abcbuzhiming  
   2020 年 4 月 21 日
@xuanbg 选 2 要面对一个预先规定功能边界问题,然而在经常变动的需求下就慢慢的这个边界就模糊了,然后你就发现照样糊在一起
nvkou
   33
nvkou  
   2020 年 4 月 21 日 via Android
后端不是已经没有 view 了吗。重点应该都在路由和业务了吧。
wweir
   34
wweir  
   2020 年 4 月 21 日
2, 不过拆分了 repo 。
整个使的是微服务的套路
uxstone
   35
uxstone  
   2020 年 4 月 21 日
没有最优

如果不对需求严加把控,最终都会变成💩山。
limingjie138
   36
limingjie138  
   2020 年 4 月 22 日 via Android
个人开发我选择了 1,但后来项目越堆越大,再开其他项目需要共用实体类的时候我就超级头痛,快点但蠢新建一个 project 把 enter 完整的 copy 过去。后悔当时不应该为了自己开发快选 1 。有没有大佬能救救我 1 的方案导致的实体不能多 project 共用的问题
huijiewei
   37
huijiewei  
   2020 年 4 月 22 日   ❤️ 1
@limingjie138 你这个问题,最简单地办法就是引入 RabbitMQ 独立事件机制,把关联做成事件关联
zhuzhibin
   38
zhuzhibin  
   2020 年 4 月 22 日
有区别吧 第二种是按照模块组织 最上层可以抽成通用的壳子 业务按照 modules 来组织 期望这些 module 都是独立可拆分的 这种做法比较难的就是业务解耦了 模块之间不要耦合太严重,否则没啥收益了
imycc
   39
imycc  
   2020 年 4 月 22 日
flask 的 blueprint 就是 2 这样的设计思路,每个模块之间各自处理内部的业务,在功能拆分还有迭代上会舒服一些。

不过即使用了 2 的结构,如果在开发时候 ABC 互相引用,到时候拆微服务也拆不开。
zclHIT
   40
zclHIT  
   2020 年 4 月 22 日 via iPhone
来吧拥抱 DDD
realpg
   41
realpg  
   2020 年 4 月 22 日
抛开项目需求谈架构都是扯
hacson
   42
hacson  
   2020 年 4 月 22 日 via iPhone
我来问个题外话,楼主你这个树形结构的图是怎么生成的?有时候分享 ppt 这种图还蛮清晰明了的
akagishigeru
   43
akagishigeru  
   2020 年 4 月 22 日 via iPhone
我和楼主同样的 两个模块之间耦合数据层( Model )该怎么办?需要连表的情况下,该如何处理呢?希望求得一知半解
Leigg
   44
Leigg  
   2020 年 4 月 22 日 via Android
这个叫代码结构
itechify
   45
itechify  
   2020 年 4 月 22 日 via Android
毫无疑问选 B
AngryMagikarp
   46
AngryMagikarp  
   2020 年 4 月 22 日
这只是代码组织方式而已,前端客户端都可以用。

没有完美的方式,只有最合适的方式,抛开需求谈这个没什么意义。
edk24
   47
edk24  
   2020 年 4 月 22 日
我怀疑你在说 tp3 和 tp5 哈哈哈
Jrue0011
   48
Jrue0011  
   2020 年 4 月 22 日
初期一个就行了,后期再拆分,遇到困难再想解决方案。。。
robot1
   49
robot1  
   2020 年 4 月 22 日
点链接之前脑子里闪现了分布式 无状态 高可用 一致性 ,点进来原来是代码放哪个文件夹。。。。。
Orenoid
   50
Orenoid  
   2020 年 4 月 22 日
业务划分得清楚,A 也可以重构成 B 。业务互相耦合,用 B 一样给写成 A 。
Muyiafan
   51
Muyiafan  
   2020 年 4 月 22 日
这不就是个文件目录吗? 怎么成服务器架构模式了!
Hanggi
   52
Hanggi  
OP
   2020 年 4 月 22 日
@Muyiafan
@robot1
@Leigg
@wangyzj

好多人都在纠结为什么叫架构模式,可能翻译的不准确,但是我们平时经常说的 MVC 、微服务都是架构模式,贴个维基百科链接:
https://zh.wikipedia.org/wiki/%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F

当你改变你的目录结构、代码组织方式、依赖管理方式等这些细节的时候,其实你已经悄然改变了你的架构模式。
FinnBai
   53
FinnBai  
   2020 年 4 月 22 日
目录结构是跟着架构走的,还是得看实际需求,所以也谈不上哪种最优
xianxiaobo
   54
xianxiaobo  
   2020 年 4 月 22 日
混起来用,以 B 为主,A 为辅。
zypy333
   55
zypy333  
   2020 年 4 月 22 日
@Hanggi 单回复你那个多表关联下的模块拆分问题,我正好前阵子看过一个房产平台微服务视频,里面提了,说这种跨模块的,最好把关联表放到被依赖关系较小的那个库里,比如说用户表被很多模块依赖,那用户-房产关联表,就放到房产模块的库里
charlie21
   56
charlie21  
   2020 年 4 月 22 日
前者不就是后者的细节展开图嘛 ...
xuanbg
   57
xuanbg  
   2020 年 4 月 22 日
@abcbuzhiming 功能边界肯定要划分清楚的呀。

我在带团队的过程中一直强调,把代码写对地方比写对代码更重要。代码写错了很快就能发现并修复问题,写错了地方则不然,当时是没问题你好我好大家好,但会让你在后面一直吃屎。。。同时也会在合并分支时产生大量的冲突。

事实上只要在写代码之前稍微思考一下再动手,就很容易解决功能边界的问题,也就能把代码写对地方了。
xuanbg
   58
xuanbg  
   2020 年 4 月 22 日
@JaguarJack A 和 B 之外搞个 Common 就行,AB 都依赖 C
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
© 2026 V2EX · 131ms · 3.9.8.5