首页 > 解决方案 > 多个线程调用相同函数的问题

问题描述

我在我的代码中有两次对应用程序的休息调用,即使调用是对同一个端点,我想区分以微米为单位的调用。为此,我正在尝试添加一个新字段,如下所示

@Component
class MyMeterFilter : MeterFilter {

    var isRequired: Boolean = false
    override fun map(id: Meter.Id): Meter.Id {
        return if (id.name.startsWith("http")) {
            id.withTag(Tag.of("extra.tag", isRequired.toString()))
        } else id
    }

}

在进行第一次调用之前,我将 isRequired 字段设置为 true,在第二次调用之前,我将其设置为 false(两个调用都是来自单例 bean 的异步)。但正如您从代码中看到的那样,由于只创建了一个类的实例,因此 isRequired 的值在两个调用之间被覆盖。我怎样才能避免它?

标签: multithreadingkotlinthread-safetymicrometerspring-micrometer

解决方案


如果它基于进行调用的线程ThreadLocal可以保持该状态,则MeterFilter可以检查它,只需确保在ThreadLocal完成后清除它。

您似乎正在尝试在http.server.request指标上设置额外的标签,对吗?这是非常聪明的。

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class MetricDecoratingFilter : OncePerRequestFilter(), MeterFilter {
    private val additionalTags = ThreadLocal<Tags>()

    override fun doFilterInternal(req: HttpServletRequest, resp: HttpServletResponse, chain: FilterChain) {
        //add logic to compute the tags
        additionalTags.set(Tags.of("app", "bob"))
        chain.doFilter(req, resp)
        additionalTags.remove()
    }

    override fun map(id: Meter.Id): Meter.Id {
        return if (id.name.startsWith("http")) {
            val moreTags = additionalTags.get()
            id.withTags(moreTags)
        } else id
    }
}

推荐阅读