记录一次解决404问题

解决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工程。
 

posted on 2018-04-21 21:15  张叫兽的技术研究院  阅读(2031)  评论(0编辑  收藏  举报

导航