dianping / cat

CAT 作为服务端项目基础组件,提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。
Apache License 2.0
18.68k stars 5.42k forks source link

Cat异步Transaction丢失Context #2131

Closed flyingglass closed 2 years ago

flyingglass commented 3 years ago

Describe the bug Cat Transaction在多个线程之间切换会丢失调用链

Expected behavior Cat Transaction可以再多个线程间传递,比如SpringCloud Gateway。 看Cat Client的源码DefaultMessageManager有变量ThreadLocal context,目前解思路在配合Java Agent的情况在比如对特定的场景(Runnable, Callable , @Async, Thread, ThreadPool, Webflux等)进行增强,完成context的传递,就能实现Transaction在上述异步场景传递的问题。

因为对Cat Client深入有限,按照上述思路除了DefaultMessageManager的context变量,是否还需要涉及到其他地方context传递问题?

zhisrc commented 2 years ago

可以尝试 forkableTransaction public class Test {

static class TestTask implements Runnable {

    ForkableTransaction m_forkable;
    int m_index;

    TestTask(ForkableTransaction t, int i) {
        m_forkable = t;
        m_index = i;
    }

    @Override
    public void run() {
        try (ForkedTransaction ignored = m_forkable.doFork()) {
            Transaction t = Cat.newTransaction("foo-" + String.valueOf(m_index), "bar");
            Thread.sleep(50);
            t.complete();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Cat.initializeByDomain("bcat");

    Transaction t = Cat.newTransaction("foo", "bar");
    try {
        ForkableTransaction ft = t.forFork();
        Thread.sleep(30);
        new Thread(new TestTask(ft, 1)).start();
        Thread.sleep(30);
        new Thread(new TestTask(ft, 2)).start();
        Thread.sleep(30);
        new Thread(new TestTask(ft, 3)).start();
        Thread.sleep(30);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        t.complete();
    }

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

zhisrc commented 2 years ago

image

flyingglass commented 2 years ago

可能使用场景略微不同,主要用于reactor框架,可能上述方式比较复杂和笨重,已采用skywalking进行处理