解決404問題
開始請求過濾是放在編程來進行判斷(在doFilter函數中做);后來發現解決請求過濾更好的方式,不是代碼的方式來進行過濾,而是在web.xml文件中增加過濾配置。加完之后不好用;后來發現是因為filter要配置為LoginAction.do,那個.do沒有添加導致了問題。
<filter-mapping>
<filter-name>tracingFilter</filter-name>
<url-pattern>/agentLoginAction.do</url-pattern>
</filter-mapping>
發現還是有404錯誤,這樣雖然不影響發送日志,但是影響分析,本來是成功的,它卻顯示404。
我決定先拿原生版本的httpClient(HttpClientBuild.create.build構建)看看是否會有這個問題。如果原生版httpClient沒問題,還是我的版本的問題;本質都是走InternalHttpClinet,那么問題一定就是攔截器的問題了。
怎么定位問題?我打算先把攔截器(TracingHttpClientBuilder里面的decorateProtocolExec以及decorateMainExec)注釋成空方法看看(注意,這個行為因為沒有及時回滾,后來導致了一些無畏的調試時間)。如果返回200就坐實是攔截器的事了,然后在逐漸放開。
后來證明注釋掉攔截器也不管用,再后來確認即使是HttpClient的Builder也不好用,之前好用是因為網站重啟之初第一次都好用,誤以為是HttpClient的Builder好用。
我突然懷疑是不是因為獲取httpClient方式的問題,每次都返回同一個httpClient導致的問題?因為我發現每次都是在頁面首次加載可以成功(返回200),但是再次走servlet的filter就報錯;於是我覺得是不是應該獲取的是HttpClient的Builder,然后再build獲得client呢?不是那么回事,因為之前其實已經直接使用HttpClientBuilder來驗證沒好用。
第一次好用會不會是因為有跳轉?但是第一次第二次都有挑戰啊;第一次和第二次區別在於第一次是會跳轉到登錄頁面,第二次是跳轉mainFrame頁面;login對應的頁面時login.jsp,但是mainFrame對應的是一個非jsp頁面(mainFrame對應一個Action,該Action返回的就是newMainFrameTab)!
<forward name="newMainFrameTab" path="
new-index-definition-tab" />
就是因為返回的是一個非jsp的路徑,所以struts認為是404(這個path一定有某種處理,就不管了),后來我自己設計了一個頁面(html),然后在struts中做配置(注意,這個測試性的配置就是下文講到的“簡單”模型),成功跳轉。
404問題解決。
對於現象要敏感,抓住之后有分析,慣性思維都是關注現象之前,比如這個問題的例子,開始以為是httpclient初始化問題,但是其實還應該分析現象之后有何不同(頁面跳轉目的地不同)
但是緊跟着發現怎么沒有連在一起的日志的,都是斷開的?
突然想到之前已經把httpClient的攔截器給注釋掉了,放開看看。放開還沒好!后來發現其實不僅僅是包裝類TracingHttpClientBuilder改了,攔截器里面的HttpClientHandler里面的實現也被我給注釋了很多。我決定把這部分從愛營銷工程里面干掉(下文有介紹,這樣處理的目的是為了交接方便),zipkinclient工程還原;回到以前的狀態,故障確定不是因為zipkinClient引起的。
之后,無錯誤的調用鏈出現了。

解決重復無用調用問題
本來以及就此OK了,但是發現很多請求是單蹦一個brave-port發來的,盡管這些請求調用了doLoginAction.do但是卻並沒有走內部流程(httpClient.execute),這是怎么回事呢?為什么Filter走了那么多次?
(開始做的簡單的echo.html的模式真心不夠,可能模擬的模型太簡單了,一旦放到真正的門戶里面才發現問題。通過這個我理解
了模型模擬的概念,很多時候還是需要在真實的環境中調試,因為你的測試環境的模型,尤其是簡單的測試代碼,導致其模型也很簡單,進而脆弱;終究還是和實際的不一致。)
我突然想到了既然是被調用了三次,那么一定會走三次調用,那么Fiddler應該可以抓包,看看到底是怎么回事;果然,原來是走了三次LoginAction里面的三個方法(見下圖),所以會調用三次,因為我的httpClient只是在doLogin()函數中有調用,所以這三個方法都沒有形成調用鏈。
看來之前對於過濾的粒度想的粗了,僅僅是agentLoginAction.do是不夠的,還要考慮method。
那么其實問題比較清楚了,只要增加對於method的處理即可。通過queryString獲取到method的內容,當且僅當是doLogin走zipkin的邏輯。問題解決。
工程代碼位置放置權衡
總是要編譯打包zipkin才能體現改動,於是我把變動的比較大brave.httpclient包拿到了愛營銷的工程下;這樣正好未來如果需要改動直接修改自己工程就可以了。那些東西放在工程外,那些東西放在工程內,需要權衡。
但是后來考慮都整合的方便,這部分代碼還是要交給門戶組,越簡單越好,於是我把這部分代碼又移回zipkinClient工程。