创建可通过多个软件包访问的全局交易ID

时间:2019-01-17 01:39:49

标签: java static transactions thread-local

所有Java专家向您问好!

我正在努力提供新的闪亮的过程可视化服务,需要您的帮助!

我的项目结构如下:

服务程序包取决于核心程序包,而核心程序包则取决于Util程序包。像这样:

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

应用程序包的主要方法从我们的代码开始。它正在调用一些使用Util包从输入中读取信息的Core方法。

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. 创建一个新的程序包,这三个程序包都将依赖于此程序包,并将“保留”每个调用的进程ID。但是如何?我应该在此软件包中使用静态类吗?一个辛格尔顿?

  2. 我已经阅读了有关ThreadLocal变量的这篇文章: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上在作业之前创建的变量。是否可以和/或建议访问此参数并将其用作唯一的事务ID?

1 个答案:

答案 0 :(得分:0)

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

以如下方式提取进程ID: org.apache.logging.log4j.ThreadContext.get("RequestId");

并在处理程序链上启动(取决于您所使用的服务): ThreadContext.put("RequestId", Objects.toString(job.getId(), (String)null));
这在收到的每一项工作中都会发生。

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