微服务与组装边界——子系统提升为独立进程

微服务首先不是一种「代码分层」,而是把一个完整系统拆成多个独立运行的服务进程。每个微服务内部再进行自己的分层。这一条线回答:① 微服务到底是什么(不是多了一层,而是子系统提升到进程级);② 为什么 Server 在 main、数据库不在(组装边界判断);③ 真正的判断标准——不是「什么东西应该在 main?」,而是「这一层的组装边界在哪里?」


一、微服务:子系统提升为独立进程

微服务首先不是一种「代码分层」,而是把一个完整系统拆成多个独立运行的服务进程。每个微服务内部再进行自己的分层。

电商系统:

1
2
3
4
5
6
整个系统
├── 用户微服务
├── 商品微服务
├── 订单微服务
├── 支付微服务
└── 库存微服务

每个微服务本身都是一个小系统

1
2
3
4
5
6
Order Service
├── Interface HTTP/REST / RPC
├── Application OrderService(业务用例)
├── Domain Order / OrderItem / OrderRule(业务模型和规则)
├── Infrastructure Database / MessageQueue / HTTP Client
└── Main / Bootstrap
  • Interface:服务入口。POST /ordersGET /orders/{id} 负责 HTTP → 解析请求 → 找到对应业务入口。RESTful API 是微服务对外暴露的入口/接口,不是业务本身。
  • Application:业务用例(CreateOrder / CancelOrder / PayOrder),组织一次完整业务流程:
1
CreateOrder → 检查商品 → 创建订单 → 扣库存 → 保存订单
  • Domain:业务模型和规则——订单是否允许取消、订单金额如何计算、订单状态如何转换。这里才是核心业务规则。
  • Infrastructure:外部能力(Database / Redis / Kafka / HTTP Client / File System)。Infrastructure 是实现外部依赖的地方,但不等于整个系统:
1
2
业务:Order
基础设施实现:MySQLOrderRepository / RedisCache / KafkaProducer

二、微服务之间怎么连接?

订单服务需要库存服务:

1
Order Service ── HTTP/RPC/Message ──→ Inventory Service

不是 Order Service → 包含 Inventory Service,而是两个独立运行的微服务。这与之前的 Service → Server → HTTP 非常类似:

1
Order Application → InventoryClient → HTTP/RPC → Inventory Service

一个微服务内部甚至会出现:Application → Client → Network


三、微服务的「组装」在哪里?

一个微服务启动时:

1
main → Bootstrap → 组装(Router + Application Service + Domain + Repository + Database + Network)→ 启动 Server
1
2
3
4
5
6
int main()
{
OrderApplication app;
app.start();
return 0;
}

OrderApplication 内部组织自己的组件。因此:

1
整个微服务 → OrderApplication(REST API + Application + Domain + Infrastructure + Server)

四、微服务 = 子系统提升到进程级别

普通子系统:在同一个程序/进程里。
微服务:独立进程、独立部署、独立运行、通过网络通信。

1
2
3
4
系统
├── 微服务 A(模块 → 组件)
├── 微服务 B(模块 → 组件)
└── 微服务 C(模块 → 组件)

微服务不是「比普通分层多了一层」,而是:

把原本一个大型系统中的某些子系统提升成独立运行、独立部署的系统。

这也解释了为什么一个微服务内部仍然可以使用 ViewModel/Service/Server、分层、组件、框架、统一组装等所有思想。


五、为什么 Server 在 main,数据库不在?

混淆了两个不同概念:

Server 是「运行时系统的启动入口/对外接口」,而 Database、Service、Repository 等通常只是 Server 内部使用的组件。

1
main → Server(Router + Service + Repository + Database ...)
1
2
3
4
5
6
int main()
{
Server server;
server.start();
return 0;
}

Server 内部:

1
2
3
4
5
6
Server::Server()
{
database_ = ...;
orderService_ = ...;
router_ = ...;
}

数据库不是「不需要实例化」,而是实例化责任属于 Server,而不是 main

main 应该只负责顶层生命周期

1
main → 创建系统 → 启动系统 → 等待系统结束

而不是:

1
2
3
4
5
6
7
8
9
int main()
{
Database db;
OrderRepository repository(db);
OrderService service(repository);
Router router(service);
HttpServer server(router);
...
}

但有一个重要例外

如果数据库本身也是一个独立子系统,完全可以:

1
2
3
4
5
6
7
int main()
{
Database database;
Server server(database);

server.start();
}

大型程序:main → Server + DatabaseSystem + CacheSystem + MessageSystem 也完全合理。区别只是谁是系统级对象,谁是子系统内部组件


六、真正的判断标准:这一层的组装边界在哪里?

不是「Database / Server 是什么名字」,而是:这个东西是不是当前这一层的独立组装边界?

网络子系统:

1
Socket + Connection + Buffer + EventLoop + Router → Server(网络子系统的组装结果)

数据库子系统:

1
ConnectionPool + Transaction + Query + Repository → Database(同样可以成为组装结果)

于是上层 main → Server + Database 完全成立。

1
2
3
4
组件组装成框架,框架再组装成系统:

Socket/Connection/EventLoop/Router → Server
ConnectionPool/Query/Transaction/Repository → Database

Server 之所以经常在 main 中出现,只是因为它通常是应用的顶层运行子系统/生命周期入口。 Database 如果也是顶层子系统,也可以在 main;如果 Database 只是 Server 的内部组件,就不在 main——两种都对。

最终应该抛弃「什么东西应该在 main?」,而改成「这一层的组装边界在哪里?」一旦确定边界,边界里面的东西由边界内部组装,边界外面只创建这个边界对象。这才是「组装不会爆炸」的核心原则。


七、这一条线的位置

1
2
3
4
5
6
7
8
拆解与组织(主题):
01 元原则
05 只有组件的子系统如何被加载(组装可以下放、分级组装树)
10 微服务与组装边界(本线:组装边界判断的进程级应用)

从指令到系统(主线):
03 多系统组成的网络通信软件(三系统协作)
微服务 = 三系统协作中「系统」边界进一步外扩:每个子系统独立成进程

与 05 的关系:05 已经给出了「组装有三层,各自对齐——入口顶层组装、子系统组装下属、组件初始化自己」。微服务就是把这套分层组装扩展到进程之间:每个进程有自己的入口(Bootstrap),入口只组装本进程的直接子系统,进程之间用协议连接——组装边界判断标准完全一致,只是边界从「函数/对象」变成了「进程/网络」。


收束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
微服务 = 子系统提升为独立进程:
普通子系统:同一进程内
微服务:独立进程、独立部署、通过网络通信

每个微服务内部仍是完整小系统:
Interface / Application / Domain / Infrastructure / Bootstrap

微服务之间 = 协议连接,不是包含:
Order Service ── HTTP/RPC ──→ Inventory Service

组装边界判断:
不是「什么东西应该在 main?」
而是「这一层有没有独立的组装边界?」
边界内由边界内部组装,边界外只创建边界对象

Server 在 main 不是因为它特殊,
而是因为它通常是顶层运行子系统/生命周期入口;
Database 如果是独立子系统也可以在 main

微服务与组装边界 = 把「组装责任随系统结构分散」扩展到进程级:子系统提升为独立进程,每个进程有自己的组装边界(Bootstrap),进程之间用协议连接。 判断标准始终是「这一层的组装边界在哪里」,而不是「什么东西应该在 main」。