<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在專案生產中紀錄檔的記錄是必不可少的,在.net專案中,要說紀錄檔元件,log4net
絕對可有一席之地,隨著公司業務的發展,微服務則必定無可避免。在跨服務中通過紀錄檔進行分析效能或者排查故障點,如何快速定位紀錄檔尤為關鍵。鏈路追蹤技術的出現正是解決這些痛點的。
分散式鏈路追蹤需要收集單次請求所經過的所有服務,而且為了知道請求細節,還需要將具體的業務紀錄檔進行串聯,而這一切的基礎就是要通過一個traceid
從頭傳到尾,相當於將該次請求過程產生的所有紀錄檔都關聯其traceid
,事後排查問題只需要知道traceid
,就可以在紀錄檔中拉出與之關聯的所有紀錄檔。
當然不是所有的公司都需要鏈路追蹤,對於一些小公司,就幾個單體系統,壓根不需要這些。比如我們使用log4net
時,會在紀錄檔模板中加入ThreadId
,例如這樣的模板
"%date [%thread] %-5level - %message%newline"
雖然並行高時我們多個使用者的請求紀錄檔都摻雜在一起,但是我們依然可以根據執行緒號將該次請求的紀錄檔進行串聯。這在大多時候都很好的解決了我們的問題。
即使在體量不大的系統中上面的執行緒號很好用了,但是哪有一點不用多執行緒的業務場景呢,當一次請求進來後可能會開多個非同步執行緒去執行,那上面的執行緒號就顯得力不從心了,就是說沒法一下將相干紀錄檔提取出來了。
但是這難不倒我們,我們可以在業務開始時自定義一個隨便字串作為該次請求的唯一標識,然後將該變數通過引數傳給下游方法,下游方法也將其一層一層接力傳下去,在列印紀錄檔時都將該欄位進行輸出,這個辦法很多人都用過吧。
難道沒有一種優雅的方式能將我們某次請求的過程(包括多執行緒)進行串聯起來的唯一標識嗎?
在ASPNetCore
中其實一直有個不起眼的屬性HttpContext.TraceIdentifier,可以說他就是框架給我們提供的traceid
,我們可以在所需要的地方都注入HttpContext
來獲取該引數,當然不許那麼麻煩,只需要給紀錄檔元件獲取到該值,在任何leave的紀錄檔輸出時紀錄檔元件將其輸出即可,這個完全沒問題,大家可以去深入研究,有些紀錄檔元件可以直接設定就可以輸出該TraceIdentifier
值到每一條紀錄檔中,也可以將其使用到跨應用呼叫時傳遞到下游服務,如http請求可以通過header攜帶該值,下游從header中獲取並作為它自己的TraceIdentifier
繼續傳遞。
ThreadLoacl
倒是熟悉,是每個執行緒之間隔離的,每個執行緒操作的都是自己執行緒的物件,能做到各個執行緒或不影響。AsyncLocal
並不是一個新特性,只是用的場景不多,很少被使用
Represents ambient data that is local to a given asynchronous control flow, such as an asynchronous method.
表示對於給定非同步控制流(如非同步方法)是本地資料的環境資料。
using System; using System.Threading; using System.Threading.Tasks; class Example { static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>(); static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>(); static async Task AsyncMethodA() { // Start multiple async method calls, with different AsyncLocal values. // We also set ThreadLocal values, to demonstrate how the two mechanisms differ. _asyncLocalString.Value = "Value 1"; _threadLocalString.Value = "Value 1"; var t1 = AsyncMethodB("Value 1"); _asyncLocalString.Value = "Value 2"; _threadLocalString.Value = "Value 2"; var t2 = AsyncMethodB("Value 2"); // Await both calls await t1; await t2; } static async Task AsyncMethodB(string expectedValue) { Console.WriteLine("Entering AsyncMethodB."); Console.WriteLine(" Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'", expectedValue, _asyncLocalString.Value, _threadLocalString.Value); await Task.Delay(100); Console.WriteLine("Exiting AsyncMethodB."); Console.WriteLine(" Expected '{0}', got '{1}', ThreadLocal value is '{2}'", expectedValue, _asyncLocalString.Value, _threadLocalString.Value); } static async Task Main(string[] args) { await AsyncMethodA(); } } // The example displays the following output: // Entering AsyncMethodB. // Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1' // Entering AsyncMethodB. // Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2' // Exiting AsyncMethodB. // Expected 'Value 2', got 'Value 2', ThreadLocal value is '' // Exiting AsyncMethodB. // Expected 'Value 1', got 'Value 1', ThreadLocal value is ''
簡單理解,就是對該變數賦值後,之影響自己個自己的子執行緒,即當前執行緒發起的其他執行緒,包括執行緒池中的執行緒,都能獲取到該值,而子執行緒修改該值,對父執行緒來說是無影響的。
而這種特性貌似就是我們尋找那種能夠優雅標記出同一次請求的特性。定義一個全域性變數,在每次請求的起點對該變數賦值一個隨機字串,然後本次請求涉及到的所有執行緒存取該值,都是我們在入口賦的值。
我們可以在任意地方定義一個全域性變數,最好是放到LogHelper之中
public static class LogHelper{ public static AsyncLocal<string> Traceid = new AsyncLocal<string>(); ... }
在授權過濾器中對該值進行賦值,一般授權過濾最先執行,可作為請求的入口點
LogHelper.TraceId.Value = Guid.NewGuid().ToString();
在log4net
的LogHelper中使用,紀錄檔模板為
"%date [%property{trace}] [%thread] %-5level - %message%newline"
public static void Info(object message) { ThreadContext.Properties["trace"] = TraceId.Value; Loger.Info(message); } ...
註冊中介軟體進行設定值,將自己的中介軟體註冊靠前點
app.Use(delegate (HttpContext ctx, RequestDelegate next) { LogHelper.TraceId.Value = ctx.TraceIdentifier; return next(ctx); });
經驗證與預期符合,該實現方式不依賴AspnetCore框架HttpContext.TraceIdentifier
,提供一種實現鏈路追蹤中傳遞TraceId
的一種思路,如有不正確之處歡迎指正,如果該思路對您有幫助,請點贊分享。
以上就是.NET core專案AsyncLocal在鏈路追蹤中的應用的詳細內容,更多關於AsyncLocal鏈路追蹤的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45