您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“怎么在zuul上做日志處理”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“怎么在zuul上做日志處理”吧!
由于zuul作為api網(wǎng)關(guān),所有的請(qǐng)求都經(jīng)過(guò)這里,所以在網(wǎng)關(guān)上,可以做請(qǐng)求相關(guān)的日志處理。
我的需求是這樣的,需要記錄請(qǐng)求的 url,ip地址,參數(shù),請(qǐng)求發(fā)生的時(shí)間,整個(gè)請(qǐng)求的耗時(shí),請(qǐng)求的響應(yīng)狀態(tài),
甚至請(qǐng)求響應(yīng)的結(jié)果等。
很顯然,需要實(shí)現(xiàn)這樣的一個(gè)功能,需要寫一個(gè)ZuulFliter,它應(yīng)該是在請(qǐng)求發(fā)送給客戶端之前做處理,并且在
route過(guò)濾器路由之后,在默認(rèn)的情況下,這個(gè)過(guò)濾器的order應(yīng)該為500-1000之間。那么如何獲取這些我需要的
日志信息呢?找RequestContext,在請(qǐng)求的生命周期里這個(gè)對(duì)象里,存儲(chǔ)了整個(gè)請(qǐng)求的所有信息。
現(xiàn)在編碼,在代碼的注釋中,做了詳細(xì)的說(shuō)明,代碼如下:
@Component public class LoggerFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.POST_TYPE; } @Override public int filterOrder() { return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); String method = request.getMethod();//氫氣的類型,post get .. Map<String, String> params = HttpUtils.getParams(request); String paramsStr = params.toString();//請(qǐng)求的參數(shù) long statrtTime = (long) context.get("startTime");//請(qǐng)求的開(kāi)始時(shí)間 Throwable throwable = context.getThrowable();//請(qǐng)求的異常,如果有的話 request.getRequestURI();//請(qǐng)求的uri HttpUtils.getIpAddress(request);//請(qǐng)求的iP地址 context.getResponseStatusCode();//請(qǐng)求的狀態(tài) long duration=System.currentTimeMillis() - statrtTime);//請(qǐng)求耗時(shí) return null; } }
現(xiàn)在讀者也許有疑問(wèn),如何得到的statrtTime,即請(qǐng)求開(kāi)始的時(shí)間,其實(shí)這需要另外一個(gè)過(guò)濾器,在網(wǎng)絡(luò)請(qǐng)求route之前(大部分耗時(shí)都在route這一步),在過(guò)濾器中,在RequestContext存儲(chǔ)一個(gè)時(shí)間即可,另寫一個(gè)過(guò)濾器,代碼如下:
@Component public class AccessFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); ctx.set("startTime",System.currentTimeMillis()); return null; } }
可能還有這樣的需求,我需要將響應(yīng)結(jié)果,也要存儲(chǔ)在log中,在之前已經(jīng)分析了,在route結(jié)束后,將從具體服務(wù)獲取的
響應(yīng)流存儲(chǔ)在RequestContext中,在SendResponseFilter過(guò)濾器寫入在HttpServletResponse中,最終返回給客戶端。那么我只需要在SendResponseFilter寫入響應(yīng)流之前把響應(yīng)流寫入到 log日志中即可,那么會(huì)引發(fā)另外一個(gè)問(wèn)題,因?yàn)轫憫?yīng)流寫入到 log后,RequestContext就沒(méi)有響應(yīng)流了,在SendResponseFilter就沒(méi)有流輸入到HttpServletResponse中,導(dǎo)致客戶端沒(méi)有任何的返回?cái)?shù)據(jù),那么解決的辦法是這樣的:
InputStream inputStream =RequestContext.getCurrentContext().getResponseDataStream(); InputStream newInputStream= copy(inputStream); transerferTolog(inputStream); RequestContext.getCurrentContext().setResponseDataStream(newInputStream);
從RequestContext獲取到流之后,首先將流 copy一份,將流轉(zhuǎn)化下字符串,存在日志中,再set到RequestContext中,
這樣SendResponseFilter就可以將響應(yīng)返回給客戶端。這樣的做法有點(diǎn)影響性能,如果不是字符流,可能需要做更多的處理工作。
到此,相信大家對(duì)“怎么在zuul上做日志處理”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。