创建可通过多个包访问的全局事务 ID

Creating a global transaction Id that is accessible through multiple packages

大家好 Java 专家!

我正在开发一项新的、闪亮的流程可视化服务,我需要你的帮助!

我的项目结构是这样的:

服务包依赖于核心包,而核心包又依赖于 Util 包。像这样:

服务
|-|- 核心
|-|-|- 实用程序

应用程序包具有代码开始处的 main 方法。它正在调用一些使用 Util 包的核心方法来从输入中读取信息。

package com.dummy.service;

public void main(Object input) {
     serviceCore.call(input);
}
package com.dummy.core;

public void call(Object input) {
     String stringInput = util.readFromInput(input);
     //Do stuff
}

package com.dummy.util;

public String readFromInput(Object input) {
     //return stuff;
}

当我想要加入可视化服务时,问题就出现了。一项要求是为每次调用服务使用唯一的事务 ID。

我的问题是 - 如何在不对代码进行过多重构的情况下在所有这些方法之间共享进程 ID?要在流程可视化工具中查看整个流程,我必须在整个调用中使用相同的 ID。我认为这将是这样的:

package com.dummy.service;

public void main(Object input) {
     processVisualization.signal(PROCESS_ID, "transaction started");
     serviceCore.call(input);
     processVisualization.signal(PROCESS_ID, "transaction ended");
}
package com.dummy.core;

public void call(Object input) {
     processVisualization.signal(PROCESS_ID, "Method call is invoked");
     String stringInput = util.readFromInput(input);
     //Do stuff
}

package com.dummy.util;

public String readFromInput(Object input) {
     processVisualization.signal(PROCESS_ID, "Reading from input");
     //return stuff;
}

我正在考虑以下内容,但所有这些都只是抽象的想法,我什至不确定是否可以实施。如果是 - 那么如何?

  1. 创建一个所有三个包都将依赖的新包,并转到 "hold" 每次调用的进程 ID。但是怎么办?我应该在这个包中使用静态 class 吗?一个单身汉?

  2. 我读过这篇关于 ThreadLocal 变量的 post:When and how should I use a ThreadLocal variable? 但我不熟悉这些,也不确定如何实现这个想法 - 它应该去像我在 1 中提到的那样单独打包?

  3. 更改方法的签名以将 id 作为变量传递。不幸的是,就时间和大规模重构的危险而言,这太昂贵了。

  4. 使用文件写入 - 将 ID 保存在整个过程中都可以访问的某个文件中。

  5. 从输入构建唯一 ID - 我认为这可能是完美的解决方案,但我们可能会在对服务的单独调用中收到相同的输入。

  6. 访问 JVM 以获取一些唯一的事务 ID。我知道当我们记录东西时,我们会在日志行中打印 RequestId。这是我们在 Log4J 配置中使用的模式: <pattern>%d{dd MMM yyyy HH:mm:ss,SSS} %highlight{[%p]} %X{RequestId} (%t) %c: %m%n</pattern> 此 RequestId 是在作业之前创建的 ThreadContext 上的一个变量。是否可以and/or 建议访问此参数并将其用作唯一交易 ID?

最后我们利用了 Log4J 的线程上下文。 这可能不是最好的解决方案,因为我们混合了同一件事的目的,但我们是这样做的:

进程id是这样提取的: org.apache.logging.log4j.ThreadContext.get("RequestId");

并在 Handler Chain 上启动(取决于您使用的服务): ThreadContext.put("RequestId", Objects.toString(job.getId(), (String)null));
这发生在收到的每份工作上。

免责声明:此解决方案尚未经过全面测试,但这是我们的方向