被自己的行为蠢哭了,意识到原因后真香!
作者 | 零一
来源 | 前端印象
这两天在学习 node 相关的知识时,做出了一些错误的行为~
在做用户登录相关业务时涉及到了 cookie、session 的存取,一搜就找到了 express-session
这个中间件,真香!配几个配置就可以自动生成 cookie
、sessionId
了
但 express-session
对于 session 的存储默认是存在内存中的
这肯定不合适!
项目一挂 或者 重启,session信息全丢了,所有用户都需要重新登录
多个进程之间也无法共享 session 数据
然后去搜了下有没有 redis(key - value
形式的数据库) 相关的库,咔,又出来两个:
redis(github上叫
node-redis
,npm上叫redis
)connect-redis
前者是提供了 js 可调用的操作 redis 数据库的底层方法;后者就是获取 redis 数据库实例,成为 express-session
存取 session 信息的载体
官网的使用说明也很清楚:
后来在我调试时发现出现了很多的问题,比如第一次调用 API(不携带cookie),接口迅速响应,并带回了 Set-cookies
头,但是! 我接口响应的数据呢???我明明返回了
最终 接口 15s 未返回,超时了
因为这个问题应该很明显了,接口是有响应返回的,但返回数据这块儿出了问题,先快速定位了问题所在,就是 express-session
、redis
、connect-redis
这三个库其中一个有问题,因为在接入这几个库之前,session存储在内存中是能正常返回的
于是我就去这几个库的 issue 里搜了一下是否有类似的问题,毕竟都是这么多 star 的库,明显的问题肯定早就被人提出来了,然而!没有
我又开始在搜索引擎搜索,也同样没有!
怎么回事... 合着就我一个人有问题,难道说...?
我要发现一个惊天大bug,然后给他们提pr,从此人生一帆风顺了?(hhhhh,不知道大家有时候有没有这样的想法)
这就开始了我的 debug 看源码之路
于是我 "咔",在 express-session
里打了个断点,同时也给 redis 服务开启了 monitor
监控,调试时发现 redis 存取值的时候 key 竟然不一致
啥玩意儿?SET 的 key 是一段 hash + cookie的json字符串
,value 是一个函数字符串(存个函数干啥?此时我非常非常疑惑);GET 的 key 却只是一小段 hash
我找到源码里存取key的位置打上了断点,发现存取值的key确实不一样,但又因为此时我还没看多少源码,所以对这块儿的逻辑我暂且表示赞同,因为可能这就是别人库的 feature 呢?
提前说明一下,最终发现破案也是因为这里,但当时的我是没法断定的
没办法了,继续从头 debug 吧
res.status(200).send({ name: '01' })
先是我接口函数里返回了 http 状态码 200(怪不得我的接口立马返回了200)
然后 send 函数调用走到了 end 函数中
看了大致的逻辑,发现 express-session
重写了 res
的 end
函数,在里面判断 session 信息有无修改,进而判断需不需要保存 session 到 store 里
// 存储原始的 end 函数
var _end = res.end;
var _write = res.write;
var ended = false;
// 重写 end 函数
res.end = function end(chunk, encoding) {// 执行额外的逻辑// ...// 最终执行原始的 end 函数return _end.call(res, chunk, encoding);
};
既然 debug 都走到 end 里了,说明问题快出来了,能猜到可能是原始的 end 函数没有被调用导致的了
走到了调用 set 函数的地方,他第一个参数传了个数组,第二个参数传了个回调函数,该回调函数执行就会走到 原始 end 函数的调用,按道理来说就没问题了啊!
我继续下一步调试,发现根本没走到回调函数里,去查了一下 this.client.set 的 TS 类型
这次又证明了 redis 为什么 SET了key为一长串字符串,value为一个函数
this.client 是 redis
这个库提供的方法,我们是将 redis
生成的实例对象传给 express-session
作为 session 存储的载体,那现在看起来是 这两个库没互相兼容??
目前内心OS:两个这么大的库,更新了都不做互相兼容的么
于是我又跑回去看文档,gan!
还记得这个图么?这是我一开始准备用这些库时看的,但我没看到这个信息:当 redis 库为 v4 版本时,createClient
时需要加一个 legacyMode: true
的参数,开启传统模式?然后再回到我刚才发现的问题,这个参数是不是就是为了兼容 express-session
的?
于是我赶紧加上这个参数,嚯,真的好了!接口也迅速返回内容了
所以最终是 redis
做了版本升级,更改了 api 的使用方式
// 旧版 redis
client.set(key, value, cb)// 新版 redis
await client.set(key, value)
确实还是新版的api使用起来舒服,换作旧版的,大家使用前可能还需要封装一下
但是 express-session
并没有更改 set 函数调用的传参方式,这也很正常,毕竟这个库只是为了 session 管理用的,而 redis
以及各种 db
库又不止是专门服务于 express-session
的,它们的关系是这样的:
然而当 db
库进行了更新,就需要中间一层来连接了,也就是类似我们本文用到的 connect-redis
,此时它们的关系是这样的
所以我们在用 connect-redis
时,传一个 legacyMode: true
参数就可以让 redis
兼容 express-session
的使用了
结论
该说啥呢,被自己蠢哭了,一开始不好好看文档,导致后面花了一天时间去排查问题,还被迫看了这么多源码,你要问我后悔吗?我又不后悔:被倒逼着去看了一个库的源码、梳理了大致的逻辑、学到了思想、巩固了 cookie、session 的知识、学会了 redis 库的调试和各种命令 和 长了个教训(以后要好好看文档)
什么时候比较适合看源码呢?当然是有需要的时候,侬,比如我这次的经历
大家千万别学我一样,粗心大意,文档还是要好好看,这就跟以前上学的时候答题不仔细看题目一样,是大忌啊!!!
往期推荐
如果让你来设计网络
用过留痕,谁动了我的档案?
一把王者的时间,我就学会了Nginx
明明还有大量内存,为啥报错“无法分配内存”?
点分享
点收藏
点点赞
点在看
被自己的行为蠢哭了,意识到原因后真香!相关推荐
- python之没事别搞多版本!-----------当我知道原因,真的被自己蠢哭了
事情的来龙去脉: 公司直接下发一个完整的接口自动化项目,要求可以用命令行的方式跑通代码.其他同事都能跑通,就我不行.pycharm报错如下: 脑瓜一洞:要不我百度看看吧! 百度关键词:usage: p ...
- 解决 unity 按住鼠标右键 WS不能前进后退(我被自己蠢哭了)
今天学习的时候突然 在sence 按住鼠标右键 WS不能前进后退 搞了半天 无意间点到 IOS是正交模式 Persp这个是透视模式 近大远小再点一下 变成这样就可以用了 时间过去好多年了其原理 也很简 ...
- 蠢哭了,debug版本可用release版本出错
记录一下本人遇到的问题,可能不适用于各位. win10 vs2015 MFC编写的一个动态库dll工程,debug版本release版本编译都通过.但是运行时debug版本可用 release版本出 ...
- 【蠢哭自己系列】Linux转到桌面目录下
一.问题描述 可以看到在$HOME路径下有中文子路径和英文子路径,我们要是想要转到英文子路径直接使用以下命令即可,但是如果想要转到中文子路径就不能单纯改一下路径名称,而是要在子路径名称前加" ...
- 【虐到哭】 10家大厂面试真题
大数据开发方向知识图谱,请点击下面的连接: <大数据方向学习面试知识图谱> 腾讯 关键词[Java基础][数据结构][操作系统][算法][数据库][缓存] 自我介绍 介绍一下你在项目中的承 ...
- 90后小学计算机课,看着看着就哭了,那些年我们90后的小学语文课本
说起最近引起热议的北大学霸杀母案,闹得是沸沸扬扬.背后引发的思考,很多文章都提到了教育问题.在压抑的家庭里,孩子学会了伪装自己,有两副面孔.如果要不是杀母的事情被曝光,大家都还以为吴谢宇是一个完美的学 ...
- 安卓开发2年,入职字节跳动那天我哭了,被裁后奋战3个月终拿下
前言 先说一下自己的个人情况,18届应届生,通过校招进入到了蘑菇街,然后一待就待了差不多2年多的时间,可惜的是今年4月份受疫情影响遇到了大裁员,而我也是其中一员.好在早有预感,提前做了准备,之前一直想 ...
- 2018福大软工实践第八次作业
目录 团队信息 分工选择 课上分工 课下分工 ToDolist alpha版本要做的事情 燃尽图 UML 用例图 状态图 活动图 类图 部署图 实例图 对象图 时序图 包图 通信图 贡献分评定 课上贡 ...
- 福大软工1816 · 第八次作业课堂实践
目录 团队信息 分工选择 课上分工 课下分工 ToDolist alpha版本要做的事情 燃尽图 UML 用例图 状态图 活动图 类图 部署图 实例图 对象图 时序图 包图 通信图 贡献分评定 课上贡 ...
最新文章
- 洛谷P2904 [USACO08MAR]跨河River Crossing 动态规划
- js 导出到excel
- 计算机辅助教学 林筑英,视频教学制作技巧.doc
- SAP Spartacus Product 明细页面 meta description 标签页的数据源
- mysql 测试与mongodb 测试对比
- jdbc事务和事务的隔离级别
- 计算机节电模式不能打开,电脑进入节电模式打不开怎么办
- Nvidia CUDA初级教程4 GPU体系架构概述
- java map 实例_java中map集合嵌套形式简单示例
- wordpress iis php,Windows IIS 上安装部署 WordPress 网站快速简要教程
- 16进制转浮点型_浮点型变量和BigDecimal的使用
- Java仓储物流项目_基于jsp的物流仓库管理系统-JavaEE实现物流仓库管理系统 - java项目源码...
- BarTender数据批量打印软件的入门操作
- HLW8032功率计+esp8266WiFi插座 mixly blynk
- 为什么要学统计学:赤裸裸的统计学
- 终端应用安全之网络流量分析
- react仿钉钉流程图-审批工作流
- 该战斗的时候战斗,该转身的时候转身,但请保持优雅
- 卸载并安装NVIDIA显卡驱动
- UE4虚幻引擎UI界面动画制作!
热门文章
- python输错了怎么办_python怎么实现输错三次密码之后锁定
- java对象底层原存储结构图解_图解图库JanusGraph系列-一文知晓“图数据“底层存储结构...
- vue组件一直注册不了_Vue自定义组件及组件的注册方法
- url存在宽字节跨站漏洞_5分钟速览丨常见的Web安全漏洞及测试方法
- 线性规划图解法求最优解_高中数学:简单的线性规划问题
- pycharm中python的默认安装路径_mac PyCharm添加Python解释器及添加package路径的方法...
- c# out关键字 vb_c# 关键字:ref 和 out
- visio图标_弱电间机柜原型图整理,可编辑!(Excel,visio,CAD)
- 【文末有福利】艺术创造规则,而不是规则创造艺术
- 2019诺贝尔化学奖: 二战老兵的传奇人生