解決了一個Web網頁顯示不全的BUG
一【BUG描述】
最近開發一個Web系統的過程中遇到了一個詭異的BUG,花了2天時間解決,感覺如釋重負。
這個BUG的現象是這樣的:一個很普通的JSP網頁,本來顯示很正常,後來我在這個html頁面上加了一些控制元件元素,並修改了下CSS, JavaScript程式碼,並加入了些中文字元。本來是覺得沒什麼問題,可是在伺服器上跑起來就發現瀏覽器上這個頁面顯示一片空白,同時其他頁面卻顯示正常。另外,我用的Tomcat版本是8.0.17。
那麼我第一反應就是這個頁面程式碼哪裡改錯了,可是我仔細看了下覺得又沒什麼問題,然後頁面字元編碼和Content-type都是顯示設定UTF-8編碼。看來前端好像沒什麼問題,然後我就在瀏覽器上檢視頁面原始碼,結果發現瀏覽器上顯示的HTML原始碼居然不完整,html頁面尾部的4~5行程式碼全部不見了。這就是導致頁面無法正常顯示的直接原因。
這個無非就兩種可能:瀏覽器資料沒有全部接收,或者伺服器資料沒有全部發送。這時,我就用WireShark抓包觀察,結果顯示tomcat伺服器在傳送資料時最後幾行資料根本就沒有傳送過來。而且這兒非常巧合,因為html資料以chunked的方式傳送,最後那幾行資料恰好應該全部在最後的一個chunked包裡面,換句話說,就是最後一個chunked包丟了。
為啥偏偏這個頁面的最後一個chunked包丟了,而其他頁面好好的呢?
這時沒別的辦法啦,只能一步一步除錯JSP頁面程式碼咯(這個耗費了我1天多的時間)。通過觀察其他正常顯示的JSP頁面與這個出問題的JSP頁面的執行流程,我發現問題出在:JSP頁面在tomcat中輸出的時候,最後一個chunked資料包在快取中沒有被flush。
二【定位】
為啥不flush?這個多種原因造成的:
- JSP頁面在通過JspWriter輸出之後,其實還留了點在快取裡面。以前一般是在JSP執行完,銷燬PageContext的時候將快取中的資料flush到網路流上,可現在作者為了提高網路效能,只是將資料flush到了較低一層的CoyoteWriter的快取中,等到整個請求-響應過程結束,再flush到網路流上。如下圖:
- 作者想法是不錯,可惜少算了一步。CoyoteWriter物件是通過一個org.apache.catalina.connector.OutputBuffer來完成資料輸出的。這個OutputBuffer物件有個suspended(暫停)標誌位,用來隨時暫停這個輸出物件,處於暫停狀態的OutputBuffer物件是不會進行資料輸出的。tomcat在完成JspWriter輸出的工作後,提前將OutputBuffer的狀態設定為suspended狀態,這一步的意思防止響應資料輸出之後又輸出其他不該輸出的資料。這個本意是好的,可是等到整個過程結束,關閉OutputBuffer物件的時候,就因為這個suspended狀態導致close這個函式還沒來得及執行flush就直接退出了。如下圖:
- 當頁面通過OutputBuffer輸出第1個chunked包的資料的時候,這個物件偷偷將這個chunked包的字元資料轉換成二進位制資料快取了起來,並沒有真正輸出到網路流中。只有等到要輸出第二個chunked包的時候,才flush快取,將第一個包的資料輸出到網路中,為第二個chunked包騰出足夠的快取空間,並快取第二個chunked包。
- 當OutputBuffer輸出第一個chunked資料包到網路中的時候,會搶先輸出的Http 響應頭,並將response物件的commited標誌設定為true(這就表示響應頭已經發送)。
- 在ErrorReportValve.invoke函式中,處理完http請求後,會判斷response物件的commited標誌是否為true,如果不是true,則將OutputBuffer的suspended標誌設定為false,保證響應資料能夠輸出。
- 好了,原因找到了:因為其他web網頁比較小,導致jsp頁面處理結束了,所有的chunked資料還在緩衝中,完全並沒有被輸出到網路中(一部分在OutputBuffer快取中,一部分在JspWriter快取中),commited標誌此時為false,等到ErrorReportValve處理時,根據commited標誌,將suspended標誌重置為false,這樣在最後關閉OutputBuffer的時候,就將所有這些快取中的資料一個個都flush到了網路上。相反,我修改的那個網頁比較大,導致OutputBuffer中途就將部分資料flush到了網路上,是的commited標誌位true,那麼ErrorReportValve也就不會將suspended標誌重置為false,導致OutputBuffer在關閉時,並不會flush殘留在快取中的資料。
三【解決】
如何解決這個bug?- 在JSP頁面最後加<% out.flush %>強制重新整理;
- 升級或者回退Tomcat 伺服器版本;
相關推薦
解決了一個Web網頁顯示不全的BUG
一【BUG描述】 最近開發一個Web系統的過程中遇到了一個詭異的BUG,花了2天時間解決,感覺如釋重負。 這個BUG的現象是這樣的:一個很普通的JSP網頁,本來顯示很正常,後來我在這個html頁面上加了一些控制元件元素,並修改了下CSS, JavaScript程式碼,並加入
【最強解決辦法】列印圖片顯示不全…
最近寫論文,由於學會要求PDF稿內的圖片大於300dpi,於是在word那兒折騰了半天。 有人推薦用LaTeX類軟體來寫作,那樣匯出畫質啊格式啊啥的都可調,而且完美……但是抱歉我只有3天時間了,來不及學這麼個用程式設計思維來寫文章的軟體。於是下列問題如何解決呢? 1. Word2013預覽裡的圖片
關於如何解決PHPCMS V9內容搜索顯示不全問題解決方案
復制 site OS search 關於 module bool ole 顯示不全 進入到phpcms/modules/search/index.php文件。 找到以下代碼: if(!empty($segment_q)) { $sql = “`siteid`= ‘$site
iOS:解決UITextView自適應高度粘貼大量文字導致顯示不全的問題
tex 顯示 輸入框 textview size self. uitext sel lec 一、描述 在UITextView輸入框中粘貼大量的文字時,UITextView內容自適應高度計算出現誤差,導致整塊文字上移消失。 二、方案 在UITextView文字改變的監聽中
【Python學習】解決pandas中打印DataFrame行列顯示不全的問題
需要 pandas pre pytho 如果 clas panda 顯示不全 可能 在使用pandas的DataFrame打印時,如果表太長或者太寬會自動只給前後一些行列,但有時候因為一些需要,可能想看到所有的行列。 所以只需要加一下的代碼就行了。 #顯示所有列 pd.se
IE8中select控制元件中的option顯示不全解決方案
select控制元件,若option的內容過長,則IE8中顯示不全,導致其內容無法顯示出來。 目前測試IE9、IE11 select控制元件都沒有問題。 其中select,可以只針對個別的select,只要替換相應的class即可。 解決方案:
Echarts 折線圖y軸標籤值太長時顯示不全的解決辦法
問題 分析 解決辦法 問題 先看一下正常的情況 再看一下顯示不全的情況 所有的資料都是從後臺取的,也就是說動態變化的,一開始的時
ScoreView巢狀Listview或GradView顯示不全問題解決
public class ListviewUtil { public static void setListViewHeightBasedOnChildren(ListView listView) { // 獲取ListView對應的Adapter
JavaScript解決select下拉框中的內容太長顯示不全的問題
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
pandas中關於DataFrame行,列顯示不全(省略)的解決辦法
有時候DataFrame中的行列數量太多,print打印出來會顯示不完全。就像下圖這樣: 列顯示不全: 行顯示不全: 新增如下程式碼,即可解決。 #顯示所有列 pd.set_option('display.max_columns', None) #顯示所有行 pd.set_opt
android全面屏顯示不全解決方案【更新中...】
一、宣告最大螢幕縱橫比(官方適配方案) Android官方提供了適配方案,即提高App所支援的最大螢幕縱橫比,實現很簡單,在AndroidManifest.xml中可做如下配置: <meta-data android:name="android.max_aspect"
C#中使用DataGridView列資訊顯示不全的解決方式
在datagridview中,將讀取到的xls表格中的資料顯示出來了,但是有一部分字沒顯示出來,非要去點下,效果如下: 然後excel中的資料是這樣的: 我想要datagridview中的資料看起來一目瞭然,像excel表格那樣,就是k9後面的4個數字也顯示全,調整
解決 select2 開啟 tags 輸入中文顯示不全的BUG
一、急著修復,不求甚解: 直接開啟 select2.full.min.js 內容複製到 https://tool.lu/js/ 點選【美化(Beutify)】按鈕,格式化一下方便閱讀。 格式化好後,搜尋 “em” 會找到如下這段程式碼 : .--------------
解決ECharts 因X軸類目過多導致重疊顯示不全的問題
https://blog.csdn.net/zheng_xiao_xin/article/details/80882113 dataZoom : [//橫向滾動條
ScrollView巢狀ListView,顯示不全和位置不是頂部的解決辦法
(1)首先寫一個listview的頁面,用ScrollView進行巢狀,注意ScrollView裡面只能有一個佈局屬性,多個可以用Linearout進行包含 <?xml version="1.0" encoding="utf-8"?> <RelativeL
修改DEDECMS文章標題長度,解決DEDECMS文章標題顯示不全
在用dede呼叫列表標題出來的時候,會發現標題文字字數顯示不完全,那是因為dede預設標題出來長度是30個字元,為了讓標題顯示完整,要做以下修改! 1、進入後臺–系統–系統設定–系統基本引數–其他選項–文件標題最大程度改為你要的長度原預設是60(這裡改為了20
android listview巢狀時,顯示不全和不能滑動的解決
在listview巢狀listview的過程中,如果我們不寫一點特殊的操作的話,可能子listview會顯示不全,並且無法滑動,那麼應該怎麼解決呢 1.子listview繼承listview,然後重寫onmeasure方法,在裡面手動的去計算高度,然後傳給super方法,這
Eclipse Maven構建WebApp專案資源目錄顯示不全的原因與解決方式
一、問題展示 1、Eclipse在使用Maven構建WebApp專案的時候,首先Maven的安裝和配置都沒有問題的,但是構建專案之後,Maven專案要求的幾個必須要有的資源目錄顯示不了:
swift3.0 tableviewcell分割線顯示不全解決方案
在viewDidLoad()新增一下程式碼 if tableView.responds(to:#selector(setter: UITableViewCell.separatorInset))
簡單解決RecyclerView巢狀的RecyclerView條目顯示不全和寬度不能鋪滿
第一個RecyclerView的Adapter @Override public MyHolder onCreateViewHolder(ViewGroup parent, int viewT