实时监控Cat之旅~分布式消息树的实现原理与测试
大众点评的老吴在InfoQ上讲了Cat之后,有不少同仁开始关注这个实时监控系统,但学习的文章甚少,在GitHub上也是一言代过,给我们这些开发人员留下了N多个疑问,一时间不知道去哪里问,向谁去问了,通常的百度和谷歌也不好使了,不过,好在经理推荐的QQ群帮了忙,认识了一些cat的前辈,经过他们的努力和我们共同的执着,终于把这块难啃的骨头啃动了!
参考代码:https://github.com/chinaboard/PureCat
完成的分布式消息树
分布式消息树实现的理论
Cat上下文,它与其它数据上下文,Http上下文,文件上下文的意思是一样的,都是指一种对象的封装,在cat里它的上下文由三个ID组成,ROOT,Parent和Child,他们类似于数据库里的联合主键,在让多个消息进行关联时,需要通过这些键值,我们在跨网络记录日志时,也需要把这三个对象传过去,在目标服务器上进行解析,然后这两个消息就组成了一个消息树了。
CatContext上下文内容
/// <summary> /// cat上下文 /// </summary> public class CatContext { /// <summary> /// 消息根ID /// </summary> public string CatRootId { get; set; } /// <summary> /// 上级消息ID /// </summary> public string CatParentId { get; set; } /// <summary> /// 当前消息ID /// </summary> public string CatChildId { get; set; } public string ContextName { get; set; } public CatContext(string contextName) { ContextName = contextName ?? Environment.MachineName; } public CatContext() : this(null) { } }
在进行分布式调用时,和java版的一样,用到了LogRemoteCallClient和LogRemoteCallServer这两个方法,前者是消息发起者调用,生成context后,将它序列化传到另外一个节点,这个节点在进行事务处理时会将自己包裹到调用方的事务时在,这也就是分布式消息树的实现原理。
需要注意的地方
在Cat里,有域的概念,即domain,我们在分布式消息树的几台服务器,必须处在同一个域下!
代码这样实现的
A节点核心代码
/* client1 -> catContext -> client2 * */ #region Cat实时监控 PureCat.PureCat.Initialize(); var context = PureCat.PureCat.DoTransaction("Do", "Test", func: () => { PureCat.PureCat.NewEvent("Do", "Test"); return PureCat.PureCat.LogRemoteCallClient("zzl"); }); var url = "http://localhost:4532/home/index"; var handler = new HttpClientHandler() { }; using (var http = new HttpClient(handler)) { http.DefaultRequestHeaders.Add("catContext", Lind.DDD.Utils.SerializeMemoryHelper.SerializeToJson(context)); var response = http.GetAsync(url).Result; var staus = response.IsSuccessStatusCode; } Console.ReadLine(); #endregion
对于分布式消息树上下文的Name,我们可以使用Guid码生成,避免冲突!
B节点核心代码
string reusult = Request.Headers.GetValues("catContext").FirstOrDefault(); var cat = Lind.DDD.Utils.SerializeMemoryHelper.DeserializeFromJson<PureCat.Context.CatContext>(reusult); PureCat.PureCat.DoTransaction("Do", "Add", () => { PureCat.PureCat.LogRemoteCallServer(cat); PureCat.PureCat.LogEvent("Do", "Add", "0", "hello distribute api123"); PureCat.PureCat.LogError(new Exception()); });
本文代码只是大叔的测试DEMO,之后还会对它进行封装与优化,敬请期待!
感谢您的阅读!