net core 微服務(wù)框架 Viper 調(diào)用鏈路追蹤

1、Viper是什么?
Viper 是.NET平臺(tái)下的Anno微服務(wù)框架的一個(gè)示例項(xiàng)目。入門(mén)簡(jiǎn)單、安全、穩(wěn)定、高可用、全平臺(tái)可監(jiān)控。底層通訊可以隨意切換thrift?grpc。?自帶服務(wù)發(fā)現(xiàn)、調(diào)用鏈追蹤、Cron 調(diào)度、限流、事件總線、CQRS 、DDD、類(lèi)似MVC的開(kāi)發(fā)體驗(yàn),插件化開(kāi)發(fā)
一個(gè)不可監(jiān)控的微服務(wù)平臺(tái)是可怕的,出了問(wèn)題?難以準(zhǔn)確定位問(wèn)題的根源, Anno則提供了一套完整的監(jiān)控體系,包括鏈路追蹤、服務(wù)占用的系統(tǒng)資源、系統(tǒng)自身?CPU、內(nèi)存、硬盤(pán)使用率實(shí)時(shí)可監(jiān)控等等。

github:
https://github.com/duyanming/Viper
文檔地址:
https://duyanming.github.io/
體驗(yàn)地址:(體驗(yàn)用戶為anno 密碼123456 同一時(shí)間一個(gè)用戶只能在一個(gè)終端登錄用戶多的時(shí)候可能發(fā)生強(qiáng)制退出的情況,稍后登錄體驗(yàn))
http://140.143.207.244/
如果對(duì)Viper不了解可以看:
1、?net core 微服務(wù) 快速開(kāi)發(fā)框架 Viper 初體驗(yàn)
2、打不死的小強(qiáng) .net core 微服務(wù) 快速開(kāi)發(fā)框架 Viper 限流
2、Viper調(diào)用鏈追蹤
當(dāng)我們進(jìn)行微服務(wù)架構(gòu)開(kāi)發(fā)時(shí),通常會(huì)劃分出多個(gè)微服務(wù),各服務(wù)之間通過(guò)RPC進(jìn)行調(diào)用。一個(gè)業(yè)務(wù)操作,可能需要多個(gè)微服務(wù)的協(xié)同才能完成,在業(yè)務(wù)調(diào)用鏈路上任何一個(gè)微服務(wù)出現(xiàn)問(wèn)題或者網(wǎng)絡(luò)出現(xiàn)問(wèn)題,都會(huì)導(dǎo)致業(yè)務(wù)失敗。隨著業(yè)務(wù)越來(lái)越復(fù)雜,微服務(wù)之間的協(xié)作也越來(lái)越多,越來(lái)越復(fù)雜。如果不能直觀的看到整個(gè)調(diào)用鏈路,那么我們就無(wú)法快速、準(zhǔn)確的定位問(wèn)題、解決問(wèn)題,有甚者出現(xiàn)服務(wù)之間出現(xiàn)死循環(huán)調(diào)用拖垮整個(gè)集群。這樣我們不僅不能?chē)L到微服務(wù)給我們帶來(lái)的好處,反而引入了一堆更復(fù)雜的問(wèn)題。因此對(duì)于一個(gè)微服務(wù)系統(tǒng)鏈路追蹤是必要的。
? Viper為服務(wù)之間調(diào)用提供了一套完善的鏈路追蹤體系。通過(guò)Viper可以清晰的看到一個(gè)調(diào)用鏈(一次業(yè)務(wù)操作)經(jīng)過(guò)了哪些微服務(wù)、每個(gè)服務(wù)消耗多少時(shí)間、是否出現(xiàn)異常、處理結(jié)果如何等等。通過(guò)鏈路追蹤體系可以分析整個(gè)業(yè)務(wù)的狀態(tài),比如那個(gè)服務(wù)或者業(yè)務(wù)操作耗時(shí)異常需要優(yōu)化,快速定位問(wèn)題解決問(wèn)題。從而更好的為整個(gè)微服務(wù)體系服務(wù)。
不僅如此還可以幫助公司新入職員工梳理梳理業(yè)務(wù)脈絡(luò),明白自己所處在的業(yè)務(wù)環(huán)節(jié)、預(yù)測(cè)系統(tǒng)可能發(fā)生的隱患,早發(fā)現(xiàn)早解決,防患于未然。
鏈路追蹤列表:

??單個(gè)鏈路追蹤示例:
下面這個(gè)調(diào)用鏈路為:

? 整個(gè)調(diào)用鏈路花費(fèi)22毫秒,最后兩個(gè)調(diào)用為并行。

?
3、Viper&Anno 遠(yuǎn)程過(guò)程調(diào)用(RPC)
Anno?框架底層Rpc采用了成熟的?thrift(首選推薦)、grpc,他們都有著高性能、跨語(yǔ)言的特點(diǎn),因此Anno框架也是一個(gè)跨語(yǔ)言的,可以輕松實(shí)現(xiàn)混合編程的框架。目前支持.net core、.net framework、java,更多的實(shí)現(xiàn)期待大家共同努力一起貢獻(xiàn)。
Thrift是一種接口描述語(yǔ)言和二進(jìn)制通訊協(xié)議,它被用來(lái)定義和創(chuàng)建跨語(yǔ)言的服務(wù)。它被當(dāng)作一個(gè)遠(yuǎn)程過(guò)程調(diào)用(RPC)框架來(lái)使用,是由Facebook為“大規(guī)模跨語(yǔ)言服務(wù)開(kāi)發(fā)”而開(kāi)發(fā)的。目前托管在Apache,更多詳細(xì)可翻閱網(wǎng)上資料。
grpc 是一個(gè)高性能、開(kāi)源和通用的 RPC 框架,面向移動(dòng)和 HTTP/2 設(shè)計(jì)。目前提供 C、Java 和 Go 語(yǔ)言版本,分別是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
gRPC 基于 HTTP/2 標(biāo)準(zhǔn)設(shè)計(jì),帶來(lái)諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多復(fù)用請(qǐng)求等特。這些特性使得其在移動(dòng)設(shè)備上表現(xiàn)更好,更省電和節(jié)省空間占用。
?
以Thrift為例來(lái)了解Anno框架
Anno框架的 Thrift接口描述文件:

namespace csharp Anno.Rpc # 命名空間
struct Micro { # 服務(wù)信息
1: string ip
2: i32 port
3: i32 timeout
4: string name
5: string nickname
6: i32 weight
}
service BrokerService { # Provider服務(wù)
string broker(1:map<string,string> input)
}
service BrokerCenter { # 注冊(cè)中心
bool add_broker(1:map<string,string> input)
listGetMicro(1:string channel)
string Invoke(1:map<string,string> input)
}

服務(wù)之間通訊的接口為?string broker(1:map

///
/// Engine 常量
///
public static class Eng
{
///
/// 命名空間
///
public const string NAMESPACE = "channel";
///
/// 類(lèi)
///
public const string CLASS = "router";
///
/// 方法
///
public const string METHOD = "method";
}

channel、router、method此三個(gè)參數(shù)是遠(yuǎn)程過(guò)程調(diào)用過(guò)程中的必須參數(shù)。
以插件 Anno.Plugs.LogicService為例

namespace Anno.Plugs.LogicService
{
using Anno.CommandBus;
public class PlatformModule : BaseModule
{
--------------省略-------------------
///
/// 獲取用戶功能
///
///
[AnnoInfo(Desc = "獲取用戶功能")]
public ActionResult GetFunc()
{
return _platformQuery.GetFunc(Profile);
}
}
}

channel 對(duì)應(yīng):Anno.Plugs.Logicrouter 對(duì)應(yīng):Platformmethod 對(duì)應(yīng):GetFunc保留關(guān)鍵字:TraceId,PreTraceId,AppName,AppNameTarget,GlobalTraceId,TTL,X-Original-For
TraceId:一次Rpc調(diào)用成為一個(gè)span,這個(gè)調(diào)用的唯一標(biāo)識(shí)為TraceId
PreTraceId:服務(wù)之間相互調(diào)用的時(shí)候PreTraceId用來(lái)標(biāo)識(shí)父子關(guān)系的父TraceId
AppName:當(dāng)前服務(wù)名稱(chēng)
AppNameTarget:目標(biāo)服務(wù)名稱(chēng)
GlobalTraceId:一次用戶操作或者是系統(tǒng)人物成為一個(gè)調(diào)用鏈,這個(gè)調(diào)用鏈的唯一標(biāo)識(shí)為GlobalTraceId
TTL:跨越的服務(wù)次數(shù)
X-Original-For:web調(diào)用的時(shí)候的用戶IP?
2、Viper調(diào)用鏈追蹤體系解析?
Viper的調(diào)用鏈?zhǔn)絻?nèi)嵌在 Anno.Rpc.Client中的,Rpc調(diào)用之前創(chuàng)建追蹤對(duì)象sys_trace記錄Request參數(shù),調(diào)用完成之后完善響應(yīng)Response結(jié)果并且把追蹤對(duì)象sys_trace寫(xiě)入內(nèi)存隊(duì)列中。然后定時(shí)定量發(fā)送到追蹤服務(wù)器。
偽代碼如下:

///
/// 追蹤隊(duì)列池
///
public static class TracePool
{
//內(nèi)存隊(duì)列
private static ConcurrentQueueTraceQueue { get; set; } = new ConcurrentQueue ();
//業(yè)務(wù)處理后推送追蹤對(duì)象到內(nèi)存隊(duì)列 TraceQueue
public static void EnQueue(sys_trace trace, string result)
{
if (trace != null)
{
trace.UseTimeMs = (DateTime.Now - trace.Timespan).TotalMilliseconds;
trace.Response = result;
TraceQueue.Enqueue(trace);
}
}
//創(chuàng)建追蹤對(duì)象
public static sys_trace CreateTrance(Dictionary<string, string> input)
{
return new sys_trace()
{
Timespan = DateTime.Now,
InputDictionary = input
};
}
///
/// 批量發(fā)送調(diào)用鏈到 追蹤服務(wù)器(定時(shí)任務(wù)會(huì)定時(shí)調(diào)用TryDequeue)
///
internal static void TryDequeue()
{
if (TraceQueue.IsEmpty)
{
return;
}
Listtraces = new List ();
ReTryDequeue:
while (!TraceQueue.IsEmpty && traces.Count < 100)
{
TraceQueue.TryDequeue(out sys_trace trace);
------------轉(zhuǎn)換追蹤對(duì)象--------------if (trace.Rlt)
{
trace.Response = null;
}
traces.Add(trace);
}
if (traces.Count <= 0)
{
return;
}
Dictionary<string, string> inputTrace = new Dictionary<string, string>
{
{Const.Enum.Eng.NAMESPACE, "Anno.Plugs.Trace"},
{Const.Enum.Eng.CLASS, "Trace"},
{Const.Enum.Eng.METHOD, "TraceBatch"},
{"traces", Newtonsoft.Json.JsonConvert.SerializeObject(traces)}
};
//發(fā)送追蹤數(shù)據(jù)
Connector.BrokerDns(inputTrace);
if (!TraceQueue.IsEmpty)
{
traces.Clear();
goto ReTryDequeue;
}
}
}

??
Viper
github:
https://github.com/duyanming/Viper
文檔地址:
https://duyanming.github.io/
體驗(yàn)地址:(體驗(yàn)用戶為anno 密碼123456 同一時(shí)間一個(gè)用戶只能在一個(gè)終端登錄用戶多的時(shí)候可能發(fā)生強(qiáng)制退出的情況,稍后登錄體驗(yàn))
http://140.143.207.244/
?
關(guān)于Viper的更多內(nèi)容,隨后更新。敬請(qǐng)關(guān)注。開(kāi)源不易,感謝Star。
【推薦】.NET Core開(kāi)發(fā)實(shí)戰(zhàn)視頻課程?★★★
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第一章 入門(mén)篇-開(kāi)篇及總體規(guī)劃
【.NET Core微服務(wù)實(shí)戰(zhàn)-統(tǒng)一身份認(rèn)證】開(kāi)篇及目錄索引
Redis基本使用及百億數(shù)據(jù)量中的使用技巧分享(附視頻地址及觀看指南)
.NET Core中的一個(gè)接口多種實(shí)現(xiàn)的依賴注入與動(dòng)態(tài)選擇看這篇就夠了
10個(gè)小技巧助您寫(xiě)出高性能的ASP.NET Core代碼
用abp vNext快速開(kāi)發(fā)Quartz.NET定時(shí)任務(wù)管理界面
在ASP.NET Core中創(chuàng)建基于Quartz.NET托管服務(wù)輕松實(shí)現(xiàn)作業(yè)調(diào)度
現(xiàn)身說(shuō)法:實(shí)際業(yè)務(wù)出發(fā)分析百億數(shù)據(jù)量下的多表查詢優(yōu)化
