node.js socket 高频率发消息导致的消息合并成一条的解决方案

avatar
Mofei Zhu

最近在完成node的一个socket实现过程中,发现了很神奇的一件事情。

过程是这样的,我们用node创建了一个server,然后监听该server的“data”事件,如下:

net.createServer(function(socket) {
    sock.on('data', function(data) {
        //得到data之后进行JSON格式化处理
        JSON.parse(data)
    }
}).listen(port, ip)

经过测试之后,我们发现一切正常,窃喜之后突然得到了这样的一个噩耗,在高并发的情况下该方法会直接报错,然后中断。

经过检查发现原来是data事件的处理上的一个问题,正常的情况下data接到的数据应该如下

{"data":"123"}

但是当我们连续向该socket发送请求的时候,会发现,只要间隔时间足够短,两条消息就会合并在一起

{"data":"123"}{"data":"123"}

这时候进行JSON.parse直然会报错。

问题的原因找到了,但是如何去解决呢?

我们想到了几个方案:

  1. 限制单个data之间的间隔时间。
  2. 对返回的值进行处理。

第一种方法简单粗暴,通过发送的时候吧所有的发送请求设置一定的时间间隔,但是!这种方法绝对是彻彻底底的反人类。

于是通过仔细观察发现了这样的规律,由于socket遵循tcp协议,所以收到的最小单位一定是一条完整的json,这样的情况下我们完全不需要担心收到半条的情况。接下来就可以全力处理多条消息合在一起的情况了。

实验了各种方法之后,我们采取了下面的正则来处理。

.match(/(\{.+?\})(?={|$)/g)

关键点是这个正则 “ /({.+?})(?={|$)/g ”,他能匹配单个的JSON字符串, 专业术语叫 “零宽断言” , 关于 “零宽断言” 后面会发文章单独说明。

这样匹配出来之后,接下来的事情就好办了,你可以用任何方法单独处理取到的每一个JSON了。