13、Nepxion Discovery 之 全链路调用链监控
在进行微服务调用的时候,为了系统的高可用性,不仅需要进行灰度发布验证服务的可用性。同时对于服务健康的监控也是很重要的一环。Nepxion Discovery
在这方面也有监控方面的集成,包含以下几个方面:
- 蓝绿灰度埋点调用链监控
- 全链路日志监控
- 全链路指标监控
1、蓝绿灰度埋点调用链监控
1.1 蓝绿灰度埋点调用链监控
关于 蓝绿灰度埋点调用链监控 官网描述得很清楚,它内置蓝绿灰度埋点,包括如下:
1. n-d-service-group - 服务所属组或者应用
2. n-d-service-type - 服务类型,分为网关端 | 服务端 | 控制台端 | 测试端,使用者只需要关注前两个即可
3. n-d-service-id - 服务ID
4. n-d-service-address - 服务地址,包括Host和Port
5. n-d-service-version - 服务版本
6. n-d-service-region - 服务所属区域
7. n-d-service-env - 服务所属环境
8. n-d-version - 版本路由值
9. n-d-region - 区域路由值
10. n-d-env - 环境路由值
11. n-d-address - 地址路由值
12. n-d-version-weight - 版本权重路由值
13. n-d-region-weight - 区域权重路由值
14. n-d-id-blacklist - 全局唯一ID屏蔽值
15. n-d-address-blacklist - IP地址和端口屏蔽值
n-d-service
开头的埋点代表是服务自身的属性n-d-
开头的埋点是蓝绿灰度传递的策略路由值
因为 Nepxion Discovery
集成了 opentracing
所以它还可以自定义外置埋点。它可以集成:
- 集成OpenTracing + Jaeger蓝绿灰度全链路监控
- 集成OpenTracing + SkyWalking蓝绿灰度全链路监控
它定义了 StrategyMonitor
接口用于集成 opentracing
监控,使用 StrategyTracer
接口用于 io.opentelemetry.api.trace.Span
相关的操作。下面是StrategyTracer
接口的定义:
StrategyTracer.java
public interface StrategyTracer {void spanBuild();void spanOutput(Map<String, String> contextMap);void spanError(Throwable e);void spanFinish();String getTraceId();String getSpanId();
}
日志监控对于 Spring Cloud Gateway、Zuul 以及 微服务都是支持的,它们都会有具体的实现类去继承 StrategyMonitor
。
Spring Cloud Gateway
public class DefaultGatewayStrategyMonitor extends StrategyMonitor implements GatewayStrategyMonitor {@Overridepublic void monitor(ServerWebExchange exchange) {spanBuild();loggerOutput();loggerDebug();spanOutput(null);}@Overridepublic void release(ServerWebExchange exchange) {loggerClear();spanFinish();}
}
Zuul
public class DefaultZuulStrategyMonitor extends StrategyMonitor implements ZuulStrategyMonitor {@Overridepublic void monitor(RequestContext context) {spanBuild();loggerOutput();loggerDebug();spanOutput(null);}@Overridepublic void release(RequestContext context) {loggerClear();spanFinish();}
}
微服务 Service
public class DefaultServiceStrategyMonitor extends StrategyMonitor implements ServiceStrategyMonitor {@Value("${" + StrategyConstant.SPRING_APPLICATION_STRATEGY_TRACER_ENABLED + ":false}")protected Boolean tracerEnabled;@Value("${" + StrategyConstant.SPRING_APPLICATION_STRATEGY_TRACER_METHOD_CONTEXT_OUTPUT_ENABLED + ":false}")protected Boolean tracerMethodContextOutputEnabled;@Autowired(required = false)private List<ServiceStrategyMonitorAdapter> serviceStrategyMonitorAdapterList;@Overridepublic void monitor(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation) {spanBuild();loggerOutput();loggerDebug();}@Overridepublic void monitor(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation, Object returnValue) {spanOutput(createContextMap(interceptor, invocation, returnValue));}@Overridepublic void error(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation, Throwable e) {spanError(e);}@Overridepublic void release(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation) {loggerClear();spanFinish();}private Map<String, String> createContextMap(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation, Object returnValue) {if (!tracerEnabled) {return null;}Map<String, String> contextMap = new HashMap<String, String>();String className = interceptor.getMethod(invocation).getDeclaringClass().getName();String methodName = interceptor.getMethodName(invocation);contextMap.put("* " + DiscoveryConstant.CLASS, className);contextMap.put("* " + DiscoveryConstant.METHOD, methodName);if (tracerMethodContextOutputEnabled) {String[] methodParameterNames = interceptor.getMethodParameterNames(invocation);Object[] arguments = interceptor.getArguments(invocation);Map<String, Object> parameterMap = ClassUtil.getParameterMap(methodParameterNames, arguments);if (CollectionUtils.isNotEmpty(serviceStrategyMonitorAdapterList)) {for (ServiceStrategyMonitorAdapter serviceStrategyMonitorAdapter : serviceStrategyMonitorAdapterList) {Map<String, String> customizationMap = serviceStrategyMonitorAdapter.getCustomizationMap(interceptor, invocation, parameterMap, returnValue);for (Map.Entry<String, String> entry : customizationMap.entrySet()) {contextMap.put("* " + entry.getKey(), entry.getValue());}}}}return contextMap;}
}
1.2 蓝绿灰度埋点Debug辅助监控
Debug辅助监控只是通过普通的System.out.println方式输出,便于开发人员在IDE上调试,在生产环境下不建议开启
对于Debug辅助监控功能的开启和关闭,需要通过如下开关做控制
# 启动和关闭Header传递的Debug日志打印,注意:每调用一次都会打印一次,会对性能有所影响,建议压测环境和生产环境关闭。缺失则默认为false
spring.application.strategy.rest.intercept.debug.enabled=true
# 启动和关闭Debug日志打印,注意:每调用一次都会打印一次,会对性能有所影响,建议压测环境和生产环境关闭。缺失则默认为false
spring.application.strategy.logger.debug.enabled=true
① 网关端和服务端自身蓝绿灰度埋点Debug辅助监控
其实就是网关或者服务端调用 StrategyMonitor#loggerDebug
会进行下面日志的打印
------------------ Logger Debug ------------------
trace-id=dade3982ae65e9e1
span-id=997e31021e9fce20
n-d-service-group=discovery-guide-group
n-d-service-type=service
n-d-service-id=discovery-guide-service-a
n-d-service-address=172.27.208.1:3001
n-d-service-version=1.0
n-d-service-region=dev
n-d-service-env=env1
n-d-service-zone=zone1
n-d-version={"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}
mobile=13812345678
user=
--------------------------------------------------
② 服务端Feign或者RestTemplate拦截输入的蓝绿灰度埋点Debug辅助监控
------- Feign Intercept Input Header Information -------
n-d-service-group=discovery-guide-group
n-d-version={"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}
n-d-service-type=gateway
n-d-service-id=discovery-guide-zuul
n-d-service-env=default
mobile=13812345678
n-d-service-region=default
n-d-service-zone=default
n-d-service-address=172.27.208.1:5002
n-d-service-version=1.0
--------------------------------------------------
上面的实现方式是 FeignStrategyInterceptor
或者 RestTemplateStrategyInterceptor
的调用它们的父类方法FeignStrategyInterceptor#interceptInputHeader
实现的
③ 服务端Feign或者RestTemplate拦截输出的蓝绿灰度埋点Debug辅助监控
------- Feign Intercept Output Header Information ------
mobile=[13812345678]
n-d-service-address=[172.27.208.1:3001]
n-d-service-env=[env1]
n-d-service-group=[discovery-guide-group]
n-d-service-id=[discovery-guide-service-a]
n-d-service-region=[dev]
n-d-service-type=[service]
n-d-service-version=[1.0]
n-d-service-zone=[zone1]
n-d-version=[{"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}]
--------------------------------------------------
上面的实现方式调用的是 FeignStrategyInterceptor#interceptOutputHeader
或者 RestTemplateStrategyInterceptor#interceptOutputHeader
实现的。
1.3 自定义埋点调用链监控
① 自定义调用链上下文参数的创建,继承 DefaultStrategyTracerAdapter
// 自定义调用链上下文参数的创建
// 对于getTraceId和getSpanId方法,在OpenTracing等调用链中间件引入的情况下,由调用链中间件决定,在这里定义不会起作用;在OpenTracing等调用链中间件未引入的情况下,在这里定义才有效,下面代码中表示从Http Header中获取,并全链路传递
// 对于getCustomizationMap方法,表示输出到调用链中的定制化业务参数,可以同时输出到日志和OpenTracing等调用链中间件,下面代码中表示从Http Header中获取,并全链路传递
public class MyStrategyTracerAdapter extends DefaultStrategyTracerAdapter {@Overridepublic String getTraceId() {return StringUtils.isNotEmpty(strategyContextHolder.getHeader(DiscoveryConstant.TRACE_ID)) ? strategyContextHolder.getHeader(DiscoveryConstant.TRACE_ID) : StringUtils.EMPTY;}@Overridepublic String getSpanId() {return StringUtils.isNotEmpty(strategyContextHolder.getHeader(DiscoveryConstant.SPAN_ID)) ? strategyContextHolder.getHeader(DiscoveryConstant.SPAN_ID) : StringUtils.EMPTY;}@Overridepublic Map<String, String> getCustomizationMap() {Map<String, String> customizationMap = new HashMap<String, String>();customizationMap.put("mobile", StringUtils.isNotEmpty(strategyContextHolder.getHeader("mobile")) ? strategyContextHolder.getHeader("mobile") : StringUtils.EMPTY);customizationMap.put("user", StringUtils.isNotEmpty(strategyContextHolder.getHeader("user")) ? strategyContextHolder.getHeader("user") : StringUtils.EMPTY);return customizationMap;}
}
在配置类里@Bean方式进行调用链类创建,覆盖框架内置的调用链适配器
@Bean
public StrategyTracerAdapter strategyTracerAdapter() {return new MyStrategyTracerAdapter();
}
② 自定义类方法上入参和出参输出到调用链,继承ServiceStrategyMonitorAdapter
// 自定义类方法上入参和出参输出到调用链
// parameterMap格式:
// key为入参名
// value为入参值
public class MyServiceStrategyMonitorAdapter implements ServiceStrategyMonitorAdapter {@Overridepublic Map<String, String> getCustomizationMap(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation, Map<String, Object> parameterMap, Object returnValue) {Map<String, String> customizationMap = new HashMap<String, String>();customizationMap.put(DiscoveryConstant.PARAMETER, parameterMap.toString());customizationMap.put(DiscoveryConstant.RETURN, returnValue != null ? returnValue.toString() : null);return customizationMap;}
}
在配置类里@Bean方式进行创建
@Bean
public ServiceStrategyMonitorAdapter serviceStrategyMonitorAdapter() {return new MyServiceStrategyMonitorAdapter();
}
③ 业务方法上获取TraceId和SpanId
public class MyClass {@Autowiredprivate StrategyMonitorContext strategyMonitorContext;public void doXXX() {String traceId = strategyMonitorContext.getTraceId();String spanId = strategyMonitorContext.getSpanId();...}
}
2、全链路日志监控
蓝绿灰度埋点日志输出,需要使用者配置logback.xml或者log4j.xml日志格式,参考如下
<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="10 seconds"><!-- Simple file output --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder --><encoder><pattern>discovery %date %level [%thread] [%X{trace-id}] [%X{span-id}] [%X{n-d-service-group}] [%X{n-d-service-type}] [%X{n-d-service-app-id}] [%X{n-d-service-id}] [%X{n-d-service-address}] [%X{n-d-service-version}] [%X{n-d-service-region}] [%X{n-d-service-env}] [%X{n-d-service-zone}] [%X{mobile}] [%X{user}] %logger{10} [%file:%line] - %msg%n</pattern><charset>UTF-8</charset></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>log/discovery-%d{yyyy-MM-dd}.%i.log</fileNamePattern><maxFileSize>50MB</maxFileSize></rollingPolicy><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><!-- Safely log to the same file from multiple JVMs. Degrades performance! --><prudent>true</prudent></appender><appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>512</queueSize><appender-ref ref="FILE" /></appender><!-- Console output --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder --><encoder><pattern>discovery %date %level [%thread] [%X{trace-id}] [%X{span-id}] [%X{n-d-service-group}] [%X{n-d-service-type}] [%X{n-d-service-app-id}] [%X{n-d-service-id}] [%X{n-d-service-address}] [%X{n-d-service-version}] [%X{n-d-service-region}] [%X{n-d-service-env}] [%X{n-d-service-zone}] [%X{mobile}] [%X{user}] %logger{10} [%file:%line] - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- Only log level WARN and above --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter></appender><!-- For loggers in the these namespaces, log at all levels. --><logger name="pedestal" level="ALL" /><logger name="hammock-cafe" level="ALL" /><logger name="user" level="ALL" /><root level="INFO"><!-- <appender-ref ref="FILE_ASYNC" /> --><appender-ref ref="STDOUT" /></root>
</configuration>
日志格式打印如下:
在这里插入代码片
3、全链路指标监控
3.1 Prometheus监控
3.2 Grafana监控
3.3 Spring-Boot-Admin监控
参考地址:
- Nepxion Discovery 全链路监控
13、Nepxion Discovery 之 全链路调用链监控相关推荐
- 11、Nepxion Discovery 之全链路界面操作蓝绿灰度发布
在之前的文章中讲过,用户可以通过 URL 请求以及配置中心进行灰度发布的操作,而且支持配置中心的灰度发布参数的动态变更.如果用户不希望使用上面的两种方式,Nepxion Discovery 框架还支持 ...
- 云原生分布式应用性能监控实践-天眼全流程调用链
一.概述 天眼是中国联通IT生产运营支撑平台,对生产运营领域提供端到端.云化架构全层级的运维工具支撑,融合人工智能与大数据技术,实现传统运维向自动化生产.智慧化运营的转变,保障4亿级用户规模系统稳定运 ...
- 如何让控件span的id调用ajax_微服务架构之「 调用链监控 」
「 调用链监控 」是在微服务兴起后才有的一种新流行的监控模式.因为在我们传统单体应用的项目中,不存在服务链/调用链的概念,所以也就根本没有调用链监控的需求了. 当我们开始微服务架构之后,我们的很多服务 ...
- 调用链监控 - Tracing - APM
调用链监控 - Tracing - APM 调用链监控原理和相关概念 调用在分布式系统中的流程简述实例 相关概念 CAT vs Zipkin vs Skywalking 埋点方式简述 APM功能简述 ...
- 微服务架构之「 调用链监控 」
「 调用链监控 」是在微服务兴起后才有的一种新流行的监控模式.因为在我们传统单体应用的项目中,不存在服务链/调用链的概念,所以也就根本没有调用链监控的需求了. 当我们开始微服务架构之后,我们的很多服务 ...
- 微服务调用链监控开源工具CAT
1 监控在微服务架构的地位 2 为何需要调用链监控? 在初期的单体应用,应用都打在一个包中,无分布式概念,监控也只需对一些埋点监控. 但是微服务时代下,很多服务在各自的包,一旦出现问题,没有调用链监控 ...
- dubbo+zipkin调用链监控
dubbo+zipkin调用链监控 原文地址:http://www.cnblogs.com/ASPNET2008/p/6709900.html 分布式环境下,对于线上出现问题往往比单体应用要复杂的多, ...
- 基于Spring Aop及log4j2的MDC实现全链路调用跟踪(traceid)
环境: Springboot:2.2.3.RELEASE Spring-boot-starter-log4j2: 2.2.2.RELEASE jdk:1.8 目标: 实现Springboot框架下的全 ...
- 调用链监控:Dapper、Istio... etc.
目录 Dapper,大规模分布式系统的跟踪系统by bigbully 2.5.1 带外数据跟踪收集 6.2 解决延迟的长尾效应 7. 其他收获 RPC服务追踪的原理与实践- SegmentFault ...
最新文章
- redis 缓存过期默认时间_缓存的必知必会:一文搞懂Redis持久化和过期机制
- 微信“红包封面”终于开放:这样免费定制!
- 【转载】基于AFNetWorking3.0的图片缓存分析
- 也谈大公司病1——正确是最大的错误
- CF1396B Stoned Game(博弈论)
- Python2.7-sqlite3
- 如何取得事件中鼠标坐标
- mysql openrowset_SQL的OPENROWSET开启和使用方法
- 骨骼动画编辑器Spine的纹理打包器(texture packer)
- 我的压缩软件选择:7zip软件+Zip格式
- ngrok 通过外网链接映射到本地机器,支持http,https
- 用php远程获取MySQL到本地,mysql本地从远程数据库导数据_MySQL
- NVelocity条件选择语法
- 解决卡米,安心卸载MIUI预装软件。
- 华为安装gsm框架_华为手机怎么安装 GMS 框架和谷歌应用?
- DAS,NAS,SAN 三种存储技术比较
- B站百万粉丝是如何做起来的?解密UP主成长之路
- docker下载gcr.io镜像
- 关于Office365邮箱附件大小限制问题
- 《Design of Computer Programs》学习笔记(2 - 1)Back of the Envelope - Lesson 2
热门文章
- 华为云云耀云服务器 中小企业的福音
- 在计算机上创建用户的密码要求,电脑设置密码在哪里设置
- Java - 为什麽 Iterator接口 不提供 add(E) 方法 ?
- 用Easy UI快速搭建一个后台
- 未来十年,都从今天开始 | 全球视角的心理AI产品应用与探索
- On ne change pas 做梦的fille
- Multi-Task Video Captioning with Video and Entailment Generation阅读笔记
- 网站提示DNS_PROBE_FINISHED_NXDOMAIN错误如何修复
- 机械键盘的“轴”有什么区别?
- DFRobot新推出一款适合短时间环境数据记录的Gravity: 串口数据记录器