dubbo鏈路跟蹤

沒(méi)有使用框架,自己寫(xiě)的簡(jiǎn)單鏈路跟蹤甸祭,主要是下面兩個(gè)過(guò)濾器TraceRpcFilter褥影、TraceHttpFilter 。

@Activate(group = {Constants.CONSUMER,Constants.PROVIDER})

public class TraceRpcFilter implements Filter {

? ? /**

? ? * 1、保證RpcContext中存在mdcData赊抖,為了下一次獲取mdcData后寫(xiě)入到MDC

? ? * 2寨典、保證MDC中存在mdcData,為了最終的日志打印輸入

? ? * @param invoker

? ? * @param invocation

? ? * @return

? ? * @throws RpcException

? ? */

? ? public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

? ? ? ? //創(chuàng)建traceId

? ? ? ? TraceUtils.createTrace();

? ? ? ? //創(chuàng)建spanId

? ? ? ? TraceUtils.createSpan();

? ? ? ? //設(shè)置parentId

? ? ? ? TraceUtils.setParent();

? ? ? ? //設(shè)置其它信息

? ? ? ? TraceUtils.setRpcOthersInfo();

? ? ? ? return invoker.invoke(invocation);

? ? }

}


public class TraceHttpFilter extends OncePerRequestFilter implements Ordered {

? ? private static final Logger logger? = LoggerFactory.getLogger(TraceHttpFilter.class);

? ? @Autowired(required = false)

? ? private TraceLogInformation traceLogInformation;

? ? @Override

? ? public int getOrder() {

? ? ? ? return 0;

? ? }

? ? /***

? ? * 生成traceId和spanId注暗,并寫(xiě)入slf4j的本地線程變量(也就意味著墓猎,請(qǐng)求中開(kāi)啟的線程和定時(shí)任務(wù)是得不到traceId和spanId的)

? ? * @Param [request, response, filterChain]

? ? * @return void

? ? **/

? ? @Override

? ? protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

? ? ? ? try {

? ? ? ? ? ? String traceId = request.getHeader("x-http-trace");//nginx可能附加的請(qǐng)求頭

? ? ? ? ? ? if (StringUtils.isEmpty(traceId)) {

? ? ? ? ? ? ? ? MDC.put(TraceConstants.TRACE_ID, TraceUtils.getLogId());

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? MDC.put(TraceConstants.TRACE_ID, traceId);

? ? ? ? ? ? }

? ? ? ? ? ? //初次調(diào)用毙沾,生成spanId

? ? ? ? ? ? MDC.put(TraceConstants.SPAN_ID, TraceUtils.getLogId());

? ? ? ? ? ? if (traceLogInformation != null) {

? ? ? ? ? ? ? ? traceLogInformation.setLocalIp(AccessIpUtils.getLocalIp());//本地IP

? ? ? ? ? ? ? ? traceLogInformation.setRemoteIp(AccessIpUtils.getRemoteIp(request));//訪問(wèn)IP

? ? ? ? ? ? ? ? TraceUtils.setHttpOthersInfo(traceLogInformation);

? ? ? ? ? ? }

? ? ? ? }catch (Exception ex){

? ? ? ? ? ? logger.error("http請(qǐng)求過(guò)濾器處理異常:{}",ex.getMessage());

? ? ? ? }

? ? ? ? filterChain.doFilter(request ,response);

? ? }

}


public class AccessIpUtils {

? ? /***

? ? * X-Forwarded-For:? ? Squid 服務(wù)代理

? ? * Proxy-Client-IP:? ? apache 服務(wù)代理

? ? * WL-Proxy-Client-IP:? weblogic 服務(wù)代理

? ? * X-Real-IP:? ? ? ? ? nginx服務(wù)代理

? ? * HTTP_CLIENT_IP:? ? ? 有些代理服務(wù)器

? ? *對(duì)http請(qǐng)求獲取請(qǐng)求IP

? ? * @Param [request]

? ? * @return java.lang.String

? ? **/

? ? public static String getRemoteIp(HttpServletRequest request) {

? ? ? ? String ip = null;

? ? ? ? String ipAddresses = request.getHeader("X-Forwarded-For");

? ? ? ? if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {

? ? ? ? ? ? ipAddresses = request.getHeader("Proxy-Client-IP");

? ? ? ? }

? ? ? ? if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {

? ? ? ? ? ? ipAddresses = request.getHeader("WL-Proxy-Client-IP");

? ? ? ? }

? ? ? ? if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {

? ? ? ? ? ? ipAddresses = request.getHeader("HTTP_CLIENT_IP");

? ? ? ? }

? ? ? ? if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {

? ? ? ? ? ? ipAddresses = request.getHeader("X-Real-IP");

? ? ? ? }

? ? ? ? //有些網(wǎng)絡(luò)通過(guò)多層代理左胞,那么獲取到的ip就會(huì)有多個(gè),一般都是通過(guò)逗號(hào)(,)分割開(kāi)來(lái)遍烦,并且第一個(gè)ip為客戶端的真實(shí)IP

? ? ? ? if (ipAddresses != null && ipAddresses.length() != 0) {

? ? ? ? ? ? ip = ipAddresses.split(",")[0];

? ? ? ? }

? ? ? ? if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {

? ? ? ? ? ? ip = request.getRemoteAddr();

? ? ? ? }

? ? ? ? return ip;

? ? }

? ? public static String getLocalIp()throws UnknownHostException{

? ? ? ? return InetAddress.getLocalHost().getHostAddress();

? ? }

}

public class TraceConstants {

? ? public static final String TRACE_TEXT_FORMAT = "[TraceId:%s]";

? ? public static final String TRACE_ID =? "traceId2";

? ? public static final String SPAN_ID? =? "spanId2";

? ? public static final String PARENT_ID =? "parentId2";

? ? public static final String APP_FLAG = UUID.randomUUID().toString();

}

public class TraceUtils {

? ? /***

? ? * 通過(guò)UUID躺枕,生成traceId拐云、spanId

? ? * @Param []

? ? * @return java.lang.String

? ? **/

? ? public static String getLogId(){

? ? ? ? return UUID.randomUUID().toString().replaceAll("-","");

? ? }

? ? /***

? ? * 生成TraceId,

? ? * 關(guān)鍵點(diǎn):traceId不應(yīng)該為空叉瘩,僅從該點(diǎn)出發(fā)判斷邏輯即可,不做任何其它邏輯上的判斷

? ? * @Param []

? ? * @return void

? ? **/

? ? public static? void? createTrace(){

? ? ? ? String? rpcTraceId? =? RpcContext.getContext().getAttachment(TraceConstants.TRACE_ID);

? ? ? ? String? mdcTraceId? =? MDC.get(TraceConstants.TRACE_ID);

? ? ? ? if(StringUtils.isEmpty(mdcTraceId)&&StringUtils.isEmpty(rpcTraceId)){

? ? ? ? ? ? rpcTraceId? =? TraceUtils.getLogId();

? ? ? ? ? ? MDC.put(TraceConstants.TRACE_ID ,rpcTraceId);

? ? ? ? ? ? RpcContext.getContext().setAttachment(TraceConstants.TRACE_ID ,rpcTraceId);

? ? ? ? }else if(StringUtils.isEmpty(mdcTraceId)&&StringUtils.isNotEmpty(rpcTraceId)){

? ? ? ? ? ? MDC.put(TraceConstants.TRACE_ID ,rpcTraceId);

? ? ? ? }else if(StringUtils.isEmpty(rpcTraceId)&&StringUtils.isNotEmpty(mdcTraceId)){

? ? ? ? ? ? RpcContext.getContext().setAttachment(TraceConstants.TRACE_ID ,mdcTraceId);

? ? ? ? }

? ? }

? ? /***

? ? * 生成SpanId,

? ? * 關(guān)鍵點(diǎn):一次調(diào)用的同一個(gè)服務(wù)中捅暴,spanId是不變的咧纠;不同的服務(wù)中,spanId是不一樣的梧奢;另外,spanId不可能為空

? ? * @Param []

? ? * @return void

? ? **/

? ? public static? void? createSpan(){

? ? ? ? String? rpcSpanId? =? RpcContext.getContext().getAttachment(TraceConstants.SPAN_ID);

? ? ? ? String? mdcSpanId? =? MDC.get(TraceConstants.SPAN_ID);

? ? ? ? if(StringUtils.isEmpty(mdcSpanId)&&StringUtils.isEmpty(rpcSpanId)){

? ? ? ? ? ? rpcSpanId? =? TraceUtils.getLogId();

? ? ? ? ? ? MDC.put(TraceConstants.SPAN_ID ,rpcSpanId);

? ? ? ? ? ? RpcContext.getContext().setAttachment(TraceConstants.SPAN_ID ,rpcSpanId);

? ? ? ? } else if(StringUtils.isEmpty(mdcSpanId)&&StringUtils.isNotEmpty(rpcSpanId)){

? ? ? ? ? ? MDC.put(TraceConstants.SPAN_ID ,TraceUtils.getLogId());

? ? ? ? }

? ? }

? ? /***

? ? * 設(shè)置parentId

? ? * 關(guān)鍵點(diǎn):同一個(gè)服務(wù)中的一次調(diào)用趋惨,parentId是不變的惦蚊;其他情況下,parentId為上一次的spanId

? ? * @Param []

? ? * @return void

? ? **/

? ? public static? void setParent(){

? ? ? ? String mdcSpanId? ? =? MDC.get(TraceConstants.SPAN_ID);

? ? ? ? String? rpcSpanId? =? RpcContext.getContext().getAttachment(TraceConstants.PARENT_ID);

? ? ? ? if(StringUtils.isNotEmpty(mdcSpanId)){

? ? ? ? ? ? RpcContext.getContext().setAttachment(TraceConstants.PARENT_ID ,mdcSpanId);

? ? ? ? }

? ? ? ? if(StringUtils.isNotEmpty(rpcSpanId)){

? ? ? ? ? ? MDC.put(TraceConstants.PARENT_ID, rpcSpanId);

? ? ? ? }

? ? }

? ? /**

? ? * 應(yīng)用名稱兆沙、Ip等信息

? ? * @Param []

? ? * @return void

? ? **/

? ? public static? void setRpcOthersInfo(){

? ? ? ? String appName = RpcContext.getContext().getUrl().getParameter("application");

? ? ? ? String localIp = RpcContext.getContext().getLocalHost();

? ? ? ? String remoteIp = RpcContext.getContext().getRemoteHost();

? ? ? ? MDC.put("appName" ,appName);

? ? ? ? MDC.put("localIp2" ,localIp);

? ? ? ? MDC.put("remoteIp2",remoteIp);

? ? }

? ? /**

? ? * 應(yīng)用名稱莉掂、Ip等信息

? ? * @Param []

? ? * @return void

? ? **/

? ? public static? void setHttpOthersInfo(TraceLogInformation traceLogInformation){

? ? ? ? MDC.put("appName" ,traceLogInformation.getApplicationName());

? ? ? ? MDC.put("localIp" ,traceLogInformation.getLocalIp());

? ? ? ? MDC.put("remoteIp" ,traceLogInformation.getRemoteIp());

? ? }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末憎妙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厘唾,更是在濱河造成了極大的恐慌,老刑警劉巖属瓣,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讯柔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡粗截,警方通過(guò)查閱死者的電腦和手機(jī)捣炬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)婿屹,“玉大人推溃,你說(shuō)我怎么就攤上這事。” “怎么了犁苏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵扩所,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我助赞,道長(zhǎng)袁勺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任婉徘,我火速辦了婚禮咐汞,結(jié)果婚禮上盖呼,老公的妹妹穿的比我還像新娘。我一直安慰自己几晤,他們只是感情好植阴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著憾朴,像睡著了一般喷鸽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上做祝,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天混槐,我揣著相機(jī)與錄音,去河邊找鬼声登。 笑死揣苏,一個(gè)胖子當(dāng)著我的面吹牛碰煌,可吹牛的內(nèi)容都是我干的绅作。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼个少,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼眯杏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起岂贩,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萎津,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锉屈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遂黍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年雾家,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绍豁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唬党,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鬼佣,到底是詐尸還是另有隱情,我是刑警寧澤晶衷,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站税迷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏慕嚷。R本人自食惡果不足惜毕泌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撼泛。 院中可真熱鬧,春花似錦损俭、人聲如沸潘酗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)囚灼。三九已至骆膝,卻和暖如春灶体,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背政钟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工樟结, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓢宦。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓驮履,卻偏偏與公主長(zhǎng)得像廉嚼,于是被迫代替她去往敵國(guó)和親倒戏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怠噪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355