前言:
重构了几次的网络库基本上没什么问题了, 从单线程改为多线程, 又从多线程改为单线程... 反反复复, 细小的地方权衡了很多次, 从简洁到复杂看不顺眼, 又重构为简洁优雅~ , OK, 扯了一堆还没进入正题, 主要唠叨一下遇到的问题和经验吧: 我们使用诸如libevent之类的网络库, 典型的用法是接受到数据包之后要一次性将数据读取完整(不完整的协议内容除外), 不过这有个问题, 一次读取完整即会触碰到缓存容量上限问题, 也会带来额外的逻辑层均衡问题, 比如, 我们希望能公平的调度每条连接上接受到数据(每个连接轮流执行一条协议).
之前想了一些, 主要的思路集中在将负载均衡的所有控制权交给网络层, 但有个问题--职责. 这样的均衡策略是易变的, 不同的项目策略肯定会大不相同, 有的希望公平调度, 有的希望按照优先级调度, 有的希望先来先得等等... 网络库不应当负责实现这样的均衡策略, 应该交给上层逻辑负责实现. 最初做了一个方案通过使用on_recv的返回值进行负载控制(返回0 停止通知, 返回1继续通知). 不过在使用的过程发现依然存在问题, 比如当前的协议并没有处理完就被挂起, 又来了一条协议要求处理, 这时我们又希望前一条协议处理完成后才进行这条协议的处理, 但是我们又不希望进行队列式的缓存, 这样就麻烦了, 如果前一条协议挂起的时间太长了, 那么后续的这条协议就只能一直被通知... 导致一定时间的CPU负载上升, 而且都是无用的...
思路:
为了解决这个棘手的问题, 又重新思考职责的问题, 到底是谁的问题, 谁该使用什么样的方式进行处理那? 让我们回想一下典型的创建netbuff的过程, 扔进去几个回调函数即可, 其实这就是一个典型的订阅服务, 网络库提供feed接口提供上层逻辑进行订阅网络消息, 但是同样我们应该提供停止订阅的途径, 毕竟只有上层逻辑最清楚何时我该订阅, 何时我该取消订阅, 所以像上面的那个问题, 在没有处理完第一条协议的时候就应该取消订阅网络消息, 处理完了再调用订阅接口重新订阅消息, 从而优雅的解决问题, 而不是简陋的通过订阅回调接口(on_recv)的返回值进行控制.
:)