從原始碼分析Request結束生命週期的處理流程

2021-09-29 23:43:53 字數 2114 閱讀 1830

最近在專案中遇到 由非同步執行任務導致的request中的請求入參物件被不同請求汙染的多執行緒問題;

在同事的研究下,發現了一把request 在原始碼層面是如何進行**處理的;因此將其中涉及到的主要原始碼進行展示:

首先,根據原始碼斷點我們發現request採用了包裝器模式,而最核心處理的request是 

org.apache.catalina.connector.request;
我們獲取請求引數的方法原始碼為:

public mapgetparametermap() 

//當未鎖住的時候進行初始化和賦值,並在賦值結束後將其鎖住

//在parametermap 被釋放鎖之後第一次呼叫執行(可能被非同步呼叫執行,可能被下乙個請求物件執行)

enumerationenumeration = getparameternames();

while (enumeration.hasmoreelements())

parametermap.setlocked(true);

return parametermap;

}

從我們獲取請求request 中的請求入參可知:  

當一次請求結束前,我們將request交給乙個非同步執行的執行緒使用,會出現兩種情況

1、在下一次請求前執行getparametermap()   方法  

2、在下一次請求後執行getparametermap()  方法

而這兩種情況都會到來問題:

首先,在下一次請求前執行getparametermap()   方法  這個時候我們的請求enumerationenumeration 物件已經被清理,沒有任何入參,並且parametermap物件被鎖住,導致下乙個請求無法進行引數設定,就會出現前端請求引數無法設定進去的現象;

第二種情況,在下一次請求後執行getparametermap()  方法,這個時候下乙個請求的入參會正常執行,但是因為下一次請求的入參被設定進來,並且我們是引用指向,parametermap物件並不會被真正的被重新建立,他只是通過lock控制了資料的安全,因此我們一步請求的執行緒依然指向下乙個介面請求的parametermap,並且其中的引數值為下乙個請求介面的入參值。

為了更便於了解真相,下面我們把request的重置方法原始碼貼出來:

public void recycle()  catch (ioexception ignored) 

}parts = null;

}partsparseexception = null;

locales.clear();

localesparsed = false;

secure = false;

remoteaddr = null;

remotehost = null;

remoteport = -1;

localport = -1;

localaddr = null;

localname = null;

attributes.clear();

sslattributesparsed = false;

notes.clear();

recyclesessioninfo();

recyclecookieinfo(false);

//入參內容儲存map,

if (globals.is_security_enabled || connector.recycle_facades) else

if (globals.is_security_enabled || connector.recycle_facades)

if (inputstream != null)

if (reader != null)

}asyncsupported = null;

if (asynccontext!=null)

asynccontext = null;

}

其中對parametermap 的操作**如下

//入參內容儲存map, 

if (globals.is_security_enabled || connector.recycle_facades) else

Request原始碼總結

看了request原始碼一周,流程懂了,但是很多細節還沒仔細查。總結一下 request.get 1.設定預設引數,allow redirects true,2.進入request方法,用session.session類持久化request 3.進入session類,設定預設請求頭,設定預設請求鉤子...

nginx原始碼分析 從原始碼看nginx框架總結

nginx原始碼總結 1 中沒有特別繞特別彆扭的編碼實現,從變數的定義呼叫函式的實現封裝,都非常恰當,比如從函式命名或者變數命名就可以看出來定義的大體意義,函式的基本功能,再好的架構實現在編碼習慣差的人實現也會黯然失色,如果透徹理解 的實現,領悟架構的設計初衷,覺得每塊 就想經過耐心雕琢一樣,不僅僅...

從原始碼分析StringUtils包

今天用到stringutils.join方法,閒來無聊,看了下原始碼 當然不可能自己分析,你傻啊,在這裡推薦乙個別人分析的 首先導包 import org.apache.commons.lang3.stringutils 我在這裡呼叫的是stringutils.join方法 public stati...