最近在完成 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 直然会报错.
问题的原因找到了, 但是如何去解决呢?
我们想到了几个方案:
限制单个 data 之间的间隔时间.
对返回的值进行处理.
第一种方法简单粗暴, 通过发送的时候吧所有的发送请求设置一定的时间间隔, 但是! 这种方法绝对是彻彻底底的反人类.
于是通过仔细观察发现了这样的规律, 由于 socket 遵循 tcp 协议, 所以收到的最小单位一定是一条完整的 json, 这样的情况下我们完全不需要担心收到半条的情况. 接下来就可以全力处理多条消息合在一起的情况了.
实验了各种方法之后, 我们采取了下面的正则来处理.
.match(/(\{.+?\})(?={|$)/g)
关键点是这个正则 "/({.+?})(?={|$)/g", 他能匹配单个的 JSON 字符串, 专业术语叫 "零宽断言" , 关于 "零宽断言" 后面会发文章单独说明.
这样匹配出来之后, 接下来的事情就好办了, 你可以用任何方法单独处理取到的每一个 JSON 了.
来源: https://www.zhuwenlong.com/blog/article/533904da1ba845cb37000002