标签:Feign 请求 Micrometer Prometheus bean Client Bean public
背景
可观测性是系统架构的基石,准确详细的度量是工程师的重要决策来源。对于微服务系统,除了传统意义上系统边界层的监控指标,服务内部调用的情况也需引起重视,这回就来分享下笔者在实现Feign调用监控的实战经验。
实现
先看看我们的监控对象:调用次数,附带标签有:服务名、uri、计数、状态码,这些信息或跟请求有关,或跟响应有关。不难想出埋点的模式无非是拦截器、过滤器链和装饰器之类,需要对请求过程前后插入环绕代码的模式。
笔者曾写过善用RequestInterceptor的文章:Feign Interceptor 拦截器实现全局请求参数 。RequestInterceptor是Feign暴露给使用者的拦截器,但只作用到请求之前,没法统计请求结果。除此之外还有改造Decoder、为@FeignClient类添加AOP环绕等手段,但最终笔者还是采用了装饰Client的方式来解决。
Client在feign中是请求的实际发送者,通过控制Client实现,就能拿到完整的请求过程。
@Slf4j
@AllArgsConstructor
public static class MetricsFeignClient implements Client {
private final Client delegate;
private final MeterRegistry meterRegistry;
@Override
public Response execute(Request request, Request.Options options) throws IOException {
Response response = null;
try {
response = delegate.execute(request, options);
} finally {
try {
meterRegistry.counter("feign_execution",
"target", request.requestTemplate().feignTarget().name(),
"uri", URLUtil.getPath(request.url()),
"status", Optional.ofNullable(response).map(Response::status).orElse(-1).toString()
).increment();
} catch (Exception e) {
log.error("error counting rpc invocation", e);
}
}
return response;
}
}
直接实现Client,通过@Bean注入,当然也能实现目的,但万万不可这样实操。编写系统组件的重要原则,就是不能影响业务,如果接入了监控代码的业务服务中自行实现了Client用作己用(也可能是引入了带自定义Client的框架,如ribbon),要么Client之间相互覆盖导致失去重要功能,要么因Bean冲突而启动失败。所以笔者认为最好的方式就是对原有Client实例进行装饰,如上文代码的delegate
字段。那么我们就需要监听到Client类创建完毕,然后用新类装饰,替换掉老的Client对象,笔者选择通过BeanPostProcessor实现。
@Slf4j
public class RpcMetricsExecutionProcessor implements BeanPostProcessor {
private volatile boolean injected = false;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!injected && bean instanceof Client) {
injected = true;
log.info("rpc execution metrics decorator injected , bean name : {} , original bean type : {} ", beanName, bean.getClass().getSimpleName());
return new MetricsFeignClient((Client) bean, registry);
}
return bean;
}
定义了BeanPostProcessor后,Bean创建完成就会回调上文中的方法,因为所有Bean创建都会回调,我们只需寻找我们需要的Client类即可。
另外笔者推荐用配置类的方式加载监控逻辑,避免业务工程没有引入Feign依赖而报错。
@Slf4j
@ConditionalOnClass(name = "feign.Client")
public class RpcMetricsExecutionConfiguration {
@Bean
public RpcMetricsExecutionProcessor rpcMetricsExecutionProcessor() {
return new RpcMetricsExecutionProcessor();
}
}
至此基本的Feign调用监控就完成了,因为掌控了请求过程,后续可以加上耗时、异常种类的统计等等。
标签:Feign,请求,Micrometer,Prometheus,bean,Client,Bean,public 来源: https://www.cnblogs.com/notayeser/p/15780997.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。