01-拆分演化
网络系统是怎么被拆成这几个组件的
主线《从函数到网络系统》第七步「组件化」只甩出一句话「网络系统拆成几个组件」。这一篇把这一步展开:网络系统从一坨职责混杂的代码,是怎么一步步被拆出 EventLoop、Connection、Session、Buffer、Protocol 的。每个组件都不是「设计出来的」,而是「扛不住什么」才被逼出来的。
一、起点:一坨混在一起的代码
最早的网络代码,所有职责混在一个 while 里:
1 | int clients[100]; |
这一个循环里,同时扛着四件事:
1 | ① 什么时候有事(遍历、等待事件) |
拆分的起点不是「想拆」,而是「这些事混在一起,改一个要动全身」。 每一件事被逼出来,就多一个组件。
二、EventLoop 被逼出来:遍历太慢
问题:100 个连接里可能只有 2 个有数据,但要逐个检查。
信号:for (i = 0; i < count; i++) 遍历全部连接,太慢。
拆分:操作系统提供高效通知(epoll/kqueue)——「只告诉谁有事,不用逐个查」。
1 | while (1) { |
拆出来的东西:EventLoop——事件循环,职责是「什么时候有事」。
驱动力:扩展(连接变多,遍历扛不住)。
1 | 拆分依据:把「等待/分发事件」从「处理单个连接」里拆出来 |
三、Connection 被逼出来:连接生死散落在回调里
问题:一条连接从 accept 到 close,中间要登记、要跟踪状态、要清理资源。这些动作散落在 EventLoop 的各个回调里。
信号:连接状态变复杂(半关闭、超时、被重置、异常断开),每个回调都要重复处理「这个连接现在什么状态」。
拆分:把「一条连接的生老病死」独立出来,交给 Connection:
1 | Connection: |
拆出来的东西:Connection——连接管理,职责是「一条连接的生死」。
驱动力:职责(连接生命周期散落各处)。
1 | 拆分依据:把「连接的生命周期」从「事件分发」里拆出来 |
四、Session 被逼出来:每个连接的状态散落
问题:每个客户端连接需要维护自己的状态——缓冲区、已收到的消息、协议状态(握手/正常/关闭)、最后活跃时间。这些状态不该散落在 EventLoop 回调里。
信号:每个连接的状态被塞进全局数组、或者靠 fd 索引到处查,改起来容易错。
拆分:把「每个连接的状态」集中到一个结构里:
1 | struct Session { |
拆出来的东西:Session——会话管理,职责是「每个连接的状态」。
驱动力:职责(状态散落)。
1 | 拆分依据:把「状态」从「事件分发」里拆出来 |
注意 Session 和 Connection 的分工:
1 | Connection:一条连接的「生命周期」(建立/关闭/清理) |
一个 Connection 上挂一个 Session——连接管「死活」,会话管「此刻是什么状态」。
五、Buffer 被逼出来:TCP 是流,一次收不到整条消息
问题:TCP 是流式协议,一次 recv 可能收到半条消息,或者两条消息粘在一起。
信号:处理消息的代码到处要判断「这条消息收全了没有」,逻辑重复且容易错。
拆分:把「字节先攒起来」这件事独立出来,交给 Buffer:
1 | Buffer: |
拆出来的东西:Buffer——缓冲区,职责是「数据暂存」。
驱动力:职责(TCP 流式 vs 消息,需要一个中间缓冲)。
1 | 拆分依据:把「暂存字节」从「收发逻辑」里拆出来 |
六、Protocol 被逼出来:裸字节没法用
问题:收发的是原始字节,调用者得自己知道「这 4 字节是命令、接下来 N 字节是数据」——每个调用者都自己猜。
信号:每个处理方都要重复定义「消息长什么样」,版本一改全乱。
拆分:把「消息长什么样」的定义独立出来,交给 Protocol:
1 | struct Message { |
拆出来的东西:Protocol——协议格式定义,职责是「消息长什么样」。
驱动力:职责(格式定义被重复写)。
1 | 拆分依据:把「格式定义」从「收发逻辑」里拆出来 |
注意:Protocol 是数据结构,不是组件——它没有算法、没有接口、没有生命周期,就是一份 struct 定义。
七、拆分演化的总表
1 | 组成部分 扛不住什么 拆分依据 性质 |
一条规律贯穿:每一步拆分的依据都是「职责」——一件事职责混杂了,就把它从另一件事里剥出来。
1 | 职责决定拆分(单一职责主题): |
八、拆分完成后,边界在哪
拆完不代表结束,还要守住边界:
1 | ✅ 网络系统只关心:字节收发、连接、会话、协议格式 |
拆分的终点不是「组件越多越好」,而是「每个组件职责单一、边界清晰」。边界一旦混了,又要重新拆。
九、和其他线的关系
1 | 本线 ←→ 拆解与组织(主题) |
收束
1 | 网络系统拆成 5 个组成部分,每一步都是「扛不住」逼出来的: |
组件不是设计出来的,是「扛不住」逼出来的。 每个组件下一篇单独展开,看它「有什么」。
