.NetCore实践篇:成功解决分布式监控ZipKin聚合依赖问题(三)
前言
读本篇文章之前,可以先读前两篇文章。为了照顾没看过的朋友,我也会稍作复习。
思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统?
实践篇一:.NetCore实践篇:分布式监控客户端ZipkinTracer从入门到放弃之路
实践篇二:.NetCore实践篇:分布式监控系统zipkin踩坑之路(二)
上一章节,我们遗留了两个问题,
聚合调用span传送到zipkin时,没有产生聚合的span。
菜单dependencies没有聚合数据,zipkin-dependencies启动失败问题。
很庆幸,这两个问题都在本篇文章得到完美解决。没有什么比一步一步解决问题更开心了,我又收集了一堆宝贵的链接。非常感谢社区,所以我也将自己的实践之路分享出来,为.net社区繁荣增一点力气。
读本篇文章之前,可以先读前两篇文章。为了照顾没看过的朋友,我也会稍作复习。
思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统?
实践篇一:.NetCore实践篇:分布式监控客户端ZipkinTracer从入门到放弃之路
实践篇二:.NetCore实践篇:分布式监控系统zipkin踩坑之路(二)
上一章节,我们遗留了两个问题,
聚合调用span传送到zipkin时,没有产生聚合的span。
菜单dependencies没有聚合数据,zipkin-dependencies启动失败问题。
很庆幸,这两个问题都在本篇文章得到完美解决。没有什么比一步一步解决问题更开心了,我又收集了一堆宝贵的链接。非常感谢社区,所以我也将自己的实践之路分享出来,为.net社区繁荣增一点力气。
zipkin复习
zipkin4net复习
zipkin4net是.NET客户端库。
它为您提供:
- Zipkin 原语(跨度,注释,二进制注释,......)【Zipkin primitives (spans, annotations, binary annotations, ...)】
- 异步跟踪发送
- 跟踪传输抽象
详情如下:
zipkin4net
zipkin4net是.NET客户端库。
它为您提供:
- Zipkin 原语(跨度,注释,二进制注释,......)【Zipkin primitives (spans, annotations, binary annotations, ...)】
- 异步跟踪发送
- 跟踪传输抽象
详情如下:
zipkin4net
zipkin-dependencies复习
这是一个Spark作业,它将从您的数据存储区收集跨度,分析服务之间的链接,并存储它们以供以后在Web UI中呈现(例如http://localhost:8080/dependency)。
什么是Spark?
Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。
此作业以UTC时间分析当天的所有跟踪。这意味着您应该将其安排在UTC午夜之前运行。
支持所有Zipkin 存储组件,包括Cassandra,MySQL和Elasticsearch。
详情如下:
zipkin-dependencies
这是一个Spark作业,它将从您的数据存储区收集跨度,分析服务之间的链接,并存储它们以供以后在Web UI中呈现(例如http://localhost:8080/dependency)。
什么是Spark?
Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。
此作业以UTC时间分析当天的所有跟踪。这意味着您应该将其安排在UTC午夜之前运行。
支持所有Zipkin 存储组件,包括Cassandra,MySQL和Elasticsearch。
详情如下:
zipkin-dependencies
今日重点--成功启动zipkin-dependencies
上次被zipkin-dependencies的启动问题卡了很晚,就结束了那篇文章,今天继续解决问题。我从网上搜到一篇类似的博文 部署生产环境时踩到的一些坑,里面提到直接在tomcat的catalina.sh的JAVA_OPTS注释处,加一行JAVA_OPTS="-server -Xms1024m -Xmx1624m -XX:PermSize=128M -XX:MaxPermSize=256m",即可解决。
# JAVA_OPTS (Optional) Java runtime options used when any command # is executed. # Include here and not in CATALINA_OPTS all options, that # should be used by Tomcat and also by the stop process, # the version command etc. # Most options should go into CATALINA_OPTS. JAVA_OPTS="-server -Xms1024m -Xmx1624m -XX:PermSize=128M -XX:MaxPermSize=256m"
tomcat启动成功。
[root@izwz9fwifc2eniq3lbdzmgz bin]# ./startup.sh Using CATALINA_BASE: /usr/local/tomcat/apache-tomcat-8.5.32 Using CATALINA_HOME: /usr/local/tomcat/apache-tomcat-8.5.32 Using CATALINA_TMPDIR: /usr/local/tomcat/apache-tomcat-8.5.32/temp Using JRE_HOME: /usr/lib/jdk1.8.0_181 Using CLASSPATH: /usr/local/tomcat/apache-tomcat-8.5.32/bin/bootstrap.jar:/usr/local/tomcat/apache-tomcat-8.5.32/bin/tomcat-juli.jar Tomcat started.
后来又搜到这条链接how to increase heap size?
原来直接在执行java命令时,追加-Xmx就行了,脑袋太死板,想不到这个点。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# java -Xmx1024m -version java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
提示内存不足,分配失败。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# STORAGE_TYPE=cassandra3 java -Xmx1024m -Xms1024m -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F` Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000d5550000, 715849728, 0) failed; error='Cannot allocate memory' (errno=12) # # There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) failed to map 715849728 bytes for committing reserved memory. # An error report file with more information is saved as: # /cusD/hs_err_pid6871.log
解决步骤:
执行刚才的vi catalina.sh,清理掉设置的JAVA_OPTs信息,关掉mysql,重启tomcat等步骤。利用free或top查看内存消耗。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# free -h total used free shared buff/cache available Mem: 1.8G 228M 1.2G 388K 396M 1.4G Swap: 0B 0B 0B
[root@izwz9fwifc2eniq3lbdzmgz cusD]# STORAGE_TYPE=cassandra3 java -Xmx512m -Xms128m -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F` 18/09/17 16:42:21 INFO CassandraDependenciesJob: Running Dependencies job for 2018-09-16: 1537056000000000 ≤ Span.timestamp 1537142399999999 18/09/17 16:42:21 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 18/09/17 16:42:22 WARN Java7Support: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added Exception in thread "main" java.io.IOException: Failed to open native connection to Cassandra at {127.0.0.1}:9042
未能加载JDK7 types,不过日志级别为Warn,可以忽略。
启动成功后,dependency依然没有数据, 需要继续查询问题。
上次被zipkin-dependencies的启动问题卡了很晚,就结束了那篇文章,今天继续解决问题。我从网上搜到一篇类似的博文 部署生产环境时踩到的一些坑,里面提到直接在tomcat的catalina.sh的JAVA_OPTS注释处,加一行JAVA_OPTS="-server -Xms1024m -Xmx1624m -XX:PermSize=128M -XX:MaxPermSize=256m",即可解决。
# JAVA_OPTS (Optional) Java runtime options used when any command # is executed. # Include here and not in CATALINA_OPTS all options, that # should be used by Tomcat and also by the stop process, # the version command etc. # Most options should go into CATALINA_OPTS. JAVA_OPTS="-server -Xms1024m -Xmx1624m -XX:PermSize=128M -XX:MaxPermSize=256m"
tomcat启动成功。
[root@izwz9fwifc2eniq3lbdzmgz bin]# ./startup.sh Using CATALINA_BASE: /usr/local/tomcat/apache-tomcat-8.5.32 Using CATALINA_HOME: /usr/local/tomcat/apache-tomcat-8.5.32 Using CATALINA_TMPDIR: /usr/local/tomcat/apache-tomcat-8.5.32/temp Using JRE_HOME: /usr/lib/jdk1.8.0_181 Using CLASSPATH: /usr/local/tomcat/apache-tomcat-8.5.32/bin/bootstrap.jar:/usr/local/tomcat/apache-tomcat-8.5.32/bin/tomcat-juli.jar Tomcat started.
后来又搜到这条链接how to increase heap size?
原来直接在执行java命令时,追加-Xmx就行了,脑袋太死板,想不到这个点。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# java -Xmx1024m -version java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
提示内存不足,分配失败。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# STORAGE_TYPE=cassandra3 java -Xmx1024m -Xms1024m -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F` Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000d5550000, 715849728, 0) failed; error='Cannot allocate memory' (errno=12) # # There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) failed to map 715849728 bytes for committing reserved memory. # An error report file with more information is saved as: # /cusD/hs_err_pid6871.log
解决步骤:
执行刚才的vi catalina.sh,清理掉设置的JAVA_OPTs信息,关掉mysql,重启tomcat等步骤。利用free或top查看内存消耗。
[root@izwz9fwifc2eniq3lbdzmgz cusD]# free -h total used free shared buff/cache available Mem: 1.8G 228M 1.2G 388K 396M 1.4G Swap: 0B 0B 0B
[root@izwz9fwifc2eniq3lbdzmgz cusD]# STORAGE_TYPE=cassandra3 java -Xmx512m -Xms128m -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F` 18/09/17 16:42:21 INFO CassandraDependenciesJob: Running Dependencies job for 2018-09-16: 1537056000000000 ≤ Span.timestamp 1537142399999999 18/09/17 16:42:21 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 18/09/17 16:42:22 WARN Java7Support: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added Exception in thread "main" java.io.IOException: Failed to open native connection to Cassandra at {127.0.0.1}:9042
未能加载JDK7 types,不过日志级别为Warn,可以忽略。
启动成功后,dependency依然没有数据, 需要继续查询问题。
今日重点--深思流程解决span聚合问题
上次是由于启动问题,今天解决了启动问题,再看不到数据,就需要深思整个流程了。
再让我们回忆下下面这张图,parentid为空,是不是意味着跨站点需要强指定parentid或站点名称?

继续翻看zipkin4Net示例代码,发现使用了IHttpClientFactory的CreateClient方法,又在ConfigureServices里指定了applicationName,也许这才是能显示出聚合站点的关键!
namespace frontend { public class Startup : CommonStartup { public override void ConfigureServices(IServiceCollection services) { services.AddHttpClient("Tracer").AddHttpMessageHandler(provider => TracingHandler.WithoutInnerHandler(provider.GetService<IConfiguration>()["applicationName"])); } protected override void Run(IApplicationBuilder app, IConfiguration config) { app.Run(async (context) => { var callServiceUrl = config["callServiceUrl"]; var clientFactory = app.ApplicationServices.GetService<IHttpClientFactory>(); using (var httpClient = clientFactory.CreateClient("Tracer")) { var response = await httpClient.GetAsync(callServiceUrl); if (!response.IsSuccessStatusCode) { await context.Response.WriteAsync(response.ReasonPhrase); } else { var content = await response.Content.ReadAsStringAsync(); await context.Response.WriteAsync(content); } } }); } } }
继续按照示例代码,修改我们的逻辑,封装一个可供其他站点调用的HTTPHelper帮助类,提供能追踪站点的GetAsync方法,
namespace Demo.ZipkinCommon { public class HTTPHelper : ControllerBase { /// <summary> /// 获取 /// </summary> /// <param name="url"></param> /// <param name="keyValues"></param> /// <param name="timeout"></param> /// <param name="encoding"></param> /// <returns></returns> public static async Task<string> GetAsync(string url, Dictionary<string, string> keyValues, int timeout = 0, Encoding encoding = null) { if (encoding == null) { encoding = Encoding.UTF8; } var appName = ConfigureSettings.AppSettingConfig["applicationName"]; using (var httpClient = new HttpClient(new TracingHandler(appName))) { var response = await httpClient.GetAsync(url); if (!response.IsSuccessStatusCode) { return response.ReasonPhrase; } else { var content = await response.Content.ReadAsStringAsync(); return content; } } } } }
两个站点的Add方法做出修正,然后查看监控数据。
[HttpPost] public IActionResult Add([FromBody]User user) { _userService.AddUser(user); //模拟调用其他站点请求。 var url = $"{ConfigEx.WebSite}/user/get?id={user.Id}"; var content = HTTPHelper.GetAsync(url, null); return Content(content.Result); }
监控spans有两级了,达到了我们要的效果




经测试,重启linux后,不开启zipkin-dependencies的情况下,内存模式下依然能实时聚合,上篇文章的结论是本人不熟悉所导致。
参考资料
源码
源码已上传范存威的github
源码已上传范存威的github
总结
基于内存模型的存储,执行效果演示到此结束。在这个过程中,提升了我java一些知识,.NetCore依赖注入,加深了zipkin整体流程的理解。
下篇文件大体方向是zipkin数据持久化和集群,以及zipkin如何跟踪mongodb和Redis。
本篇到此结束,感谢观看!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述