日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

被自己的行为蠢哭了,意识到原因后真香!

發布時間:2024/8/23 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 被自己的行为蠢哭了,意识到原因后真香! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 |?零一

來源 |?前端印象

這兩天在學習 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

明明還有大量內存,為啥報錯“無法分配內存”?

點分享

點收藏

點點贊

點在看

總結

以上是生活随笔為你收集整理的被自己的行为蠢哭了,意识到原因后真香!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。