easy_sock icon indicating copy to clipboard operation
easy_sock copied to clipboard

重构

Open alsotang opened this issue 8 years ago • 5 comments

不好意思,后面补上测试。

外部使用的话,没有任何改变。

这个重构只是针对内部逻辑,把各个状态变化都抽象成了方法。

alsotang avatar Dec 31 '15 14:12 alsotang

ping @xosuperpig

alsotang avatar Dec 31 '15 14:12 alsotang

现在测试有了

alsotang avatar Dec 31 '15 19:12 alsotang

这个重构包括以下部分:

一、 currentSession 和 context 建立映射关系,不再单独维护 currentSession 变量。

currentSession 只是对 easysock.context.keys 的数量表示

二、 将 settimeout timer 进行统一管理和回收

目前多处存在的问题是。

假如一个 write 请求发出后,它的 timer 就会存在。只有当 write 成功之后才会 clear 这个 timer。如果这时候 errorCall 发生了,会去调用该 write 对应的 callback。且该 write 永远不会成功。于是该 timer 会在到期时,重复调用 callback 一次。

三、easysock 的状态(正在关闭,正在初始化等),不再单独用分离的变量表示,而是用一个不可回退的 state 变量来跟踪。

四、非 keepAlive 时,将【一旦空闲,马上断开连接】的逻辑改成,空闲一定时间后,再断开。并统一了 tryCloseSocket 和 .close 方法。

五、抽象了一个 restore 方法,可以在初始化以及销毁 socket 时同时使用。将 easysock 实例的状态置原。以及 .close 方法自带各种回收逻辑。

错误处理方面,目前多处存在 socket 销毁后,没有及时通知正在等待中的外部 callback 函数。以及没有将实例状态复原。

六、将原来原来散落的 tryCloseSocket 和 handleData、initSocket 改写成了实例方法

七、实例初始化时即开始初始化 socket,而非第一次 write 时

八、加入了事件机制

原来一些只能通过打印日志察觉的错误,目前可以通过监听 error 事件得到

九、统一了网络一次返回n个结果包和1个结果包的数据处理逻辑。代码缩减不少。

以上这些都在测试代码里面测了,这个库写起来,状态的管理还是有点复杂。

alsotang avatar Dec 31 '15 21:12 alsotang

看了下重构的版本,代码结构化好了不少。errorcall确实有个bug,多谢提醒。另外说下一些建议: 1、重构后的接收请求代码,每次都会调用slice方法(var buf = totalData.slice(0, packageSize);),在只有一个完整回包的情况下会拷贝多一次buffer。另外会多调用一次空的isReceiveComplete,性能有点开销。 2、当时没有把所有方法挂到对象上,是考虑到不希望外部直接调用 3、在close连接的时候似乎没有判断当前是否还有未完成的会话,全部以出错回调,对外部来说不是很好控制。 @alsotang

ysbcc avatar Jan 04 '16 13:01 ysbcc

1、 这个多余 slice 的问题我有测过,问题不大。我写了个 benchmark 的文件,直接跑能跑通的那种。加上判断让它不 slice 的时候,对于性能基本没有影响。因为 slice 这个操作本身是每秒上千万 ops 的。

至于多拷贝一份 buffer,我不太清楚这个问题到底会不会存在,因为在只有一个完整包的情况下,其实我们起始的 index >= buffer.length,所以这时候,拷贝究竟是发生了还是没发生,至少是不影响性能的。

拷贝这个地方,我还做过这样的测试。由于我们的 totoalData 每次都是初始化为 Buffer(''),而每次使用的时候,我们都是把它跟其他的 slice 或者 concat,并不修改它。我试着定义了一个常量 var EMPTY_BUFFER = new Buffer(''),然后在需要的时候使用它。可是性能确实没有提升。。

看来这个库在使用时,最大的开销是网络 io 上的。

2、 这。。。是个老话题了。动态语言从来就没法很好的做到这一点。只能说在注释里面说明一下。毕竟外界在调用一些开发者不希望调用的方法时,一定要看源码才能知道方法名,注释里的提示是足够的。

3、 这一点需要我们好好探讨一下。目前我这个 close 方法是真正做了 close 的事情。以前的两个 close 和 tryCloseSocket 都属于那种没事可以调用两下的。所以我觉得吧,目前的 close 方法还是有必要存在的,这是个强制的、完全的清理。至于究竟在什么时候才应该调这个清理,让外界全部返回错的话。是不是可以再实现一个 tryClose,或者在调用 close 的时候,确定自己明白自己调的是什么。

而且目前,以前很多直接销毁 socket 的地方,我现在都是 emit('error') 而已。调用 close 的地方,一般是 socket 自身出了错,实在没法接受请求了。我们可以具体点看看各个调用了 close 的地方。

alsotang avatar Jan 05 '16 02:01 alsotang