nodejs问题是怎么样排查的
发表于:2024-11-26 作者:千家信息网编辑
千家信息网最后更新 2024年11月26日,nodejs问题是怎么样排查的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。相信大家都遇到过Error: read EC
千家信息网最后更新 2024年11月26日nodejs问题是怎么样排查的
这是连接成功后执行的nodejs回调。回调里执行了新建一个socket表示和客户端通信的对象。我们看new Socket做了什么事情。
new Socket的主要逻辑有
1 保存和客户端通信的handle(socket)
2 注册读回调
3 注册读事件
我们先看第三点
socket是可读可写的流,read(0)直接调用可读流的函数,可读流提供了抽象的逻辑,具体的读取操作由子类实现(实现_read函数,可读取的read会调用_read函数)。我们看一下Socket类_read函数的实现。
直接调用handle的readStart函数。因为我们这里使用的是tcp服务。所以handle对应的实现在tcp_wrap.cc里。但是我们发现tcp_wrap.cc没有readStart函数。一路往父类找,最终在stream_wrap.cc找到了该函数。
该函数直接调用libuv的uv_read_start函数,三个入参分别是
1 uv_tcp_t结构体
2 分配内存保存读取的数据
3 读取后执行的回调(包括读取失败)
继续往下走。
这时候nodejs就在底层注册了一个可读事件,等到有数据或者发送出错的时候,会触发上层回调(虽然只注册了可读事件,但是如果有错误发生,epoll会返回POLLIN和POLLERR事件)。这时候客户端发送了一个rst。这时候会执行libuv的回调uv__stream_io(而不是nodejs传进来那个,那个read_cb,read_cb是由libuv回调的)
接着我们看uv_read
重点在read函数,我们不妨多看点代码,看一下rst和read在linux下的实现。
上面是操作系统收到一个rst包时的操作。设置对应socket的错误信息为ECONNRESET,并设置状态为close。如果这时候用户执行read会怎样呢?
read函数会直接把错误信息返回给调用方。我们回到libuv中,当libuv调用read函数的时候,返回了错误码ECONNRESET。然后libuv执行nodejs的read_cb回调。如果我们还记得的话,nodejs提供的回调是OnUvRead。
nodejs套了很多层,不过我们还是找到了他,最后的MakeCallback(env->onread_string(), arraysize(argv), argv)就是执行js层的onread函数。这个函数我们一开始的时候也提到了。回到net.js。
nodejs的onread函数执行了destroy函数。这里就不具体展开,destroy做的事情就是调用_destroy函数。然后emit一个error事件,并传入一个Error对象(包含了错误码和系统调用函数等信息)。触发error事件的时候,我们就输出了read ECONNRESET。至此,整个源码分析过程结束。
nodejs问题是怎么样排查的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
相信大家都遇到过Error: read ECONNRESET这个错误。虽然通过ECONNRESET错误码我们很容易查到这个错误意味着什么,但是通过源码和分析工具进行一次彻底的分析,会让你更加了解这个错误的产生和原理。更让人神清气爽。
下面分为两个部分,首先通过nodejs源码分析这个错误产生的原因,然后通过网络工具抓包的方式捕获这个错误。
1 源码分析
我们从建立一个tcp连接成功后,nodejs执行的操作开始分析(net.js)。
这是连接成功后执行的nodejs回调。回调里执行了新建一个socket表示和客户端通信的对象。我们看new Socket做了什么事情。
new Socket的主要逻辑有
1 保存和客户端通信的handle(socket)
2 注册读回调
3 注册读事件
我们先看第三点
socket是可读可写的流,read(0)直接调用可读流的函数,可读流提供了抽象的逻辑,具体的读取操作由子类实现(实现_read函数,可读取的read会调用_read函数)。我们看一下Socket类_read函数的实现。
直接调用handle的readStart函数。因为我们这里使用的是tcp服务。所以handle对应的实现在tcp_wrap.cc里。但是我们发现tcp_wrap.cc没有readStart函数。一路往父类找,最终在stream_wrap.cc找到了该函数。
该函数直接调用libuv的uv_read_start函数,三个入参分别是
1 uv_tcp_t结构体
2 分配内存保存读取的数据
3 读取后执行的回调(包括读取失败)
继续往下走。
这时候nodejs就在底层注册了一个可读事件,等到有数据或者发送出错的时候,会触发上层回调(虽然只注册了可读事件,但是如果有错误发生,epoll会返回POLLIN和POLLERR事件)。这时候客户端发送了一个rst。这时候会执行libuv的回调uv__stream_io(而不是nodejs传进来那个,那个read_cb,read_cb是由libuv回调的)
接着我们看uv_read
重点在read函数,我们不妨多看点代码,看一下rst和read在linux下的实现。
上面是操作系统收到一个rst包时的操作。设置对应socket的错误信息为ECONNRESET,并设置状态为close。如果这时候用户执行read会怎样呢?
read函数会直接把错误信息返回给调用方。我们回到libuv中,当libuv调用read函数的时候,返回了错误码ECONNRESET。然后libuv执行nodejs的read_cb回调。如果我们还记得的话,nodejs提供的回调是OnUvRead。
nodejs套了很多层,不过我们还是找到了他,最后的MakeCallback(env->onread_string(), arraysize(argv), argv)就是执行js层的onread函数。这个函数我们一开始的时候也提到了。回到net.js。
nodejs的onread函数执行了destroy函数。这里就不具体展开,destroy做的事情就是调用_destroy函数。然后emit一个error事件,并传入一个Error对象(包含了错误码和系统调用函数等信息)。触发error事件的时候,我们就输出了read ECONNRESET。至此,整个源码分析过程结束。
2 抓包分析
登录服务器,使用tcpdump工具,主要是过滤出想要的数据包。这里找出有问题的那几个ip。过滤条件设置为
tcpdump -i any -q -A -nn src ip1 or dst ip1 or src ip2 or dst ip2 -w tcp.cap
保存为cap文件,然后下载到wireshark分析(linux下分析会比较麻烦点)。最后发现同一个时间点,抓包和日志系统都输出了相关的错误。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。
函数
错误
分析
事件
时候
源码
信息
客户
客户端
工具
数据
系统
问题
成功
事情
对象
就是
逻辑
帮助
服务
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
临安区软件开发平台
服务器风扇控制电路
酷通加速服务器app下载
企业数据库信息多久更新一次
怎么降低服务器的风险
国三网络技术考前押题
安平吉泰网络技术支持
台南有哪些软件开发公司
做软件开发电脑什么配置好
计算机网络技术名词简写
sapb1系统用什么数据库
上海复创互联网科技上市
招远管理系统软件开发解决方案
网络安全防护与系统安全防护
网络连接的服务器怎么删除
浙江通用软件开发零售价格
软件开发权限控制
豫苗通服务器异常是什么原因
fifa ol3数据库
服务器警告申诉信英文
警营网络安全视频
网络安全法简述的意义
网络安全国家事件
网络安全手抄报简单好看字又少
阿里云博士后网络安全
食品快检方法数据库
数据库由那两个组成
数据库显示config
网络技术专业在山东有哪些学校
洛圣都服务器管理员