Skip to content

Latest commit

 

History

History
470 lines (354 loc) · 32.9 KB

README-EN.md

File metadata and controls

470 lines (354 loc) · 32.9 KB

📌 TransmittableThreadLocal(TTL)

Build Status Coverage Status Maintainability JDK support License Javadocs Maven Central GitHub release Chat at gitter.im GitHub Stars GitHub Forks user repos GitHub issues GitHub Contributors GitHub repo size

📖 English Documentation | 📖 中文文档



🔧 Functions

👉 TransmittableThreadLocal(TTL): The missing Java™ std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components. Support Java 17/16/15/14/13/12/11/10/9/8/7/6.

Class InheritableThreadLocal in JDK can transmit value to child thread from parent thread.

But when use thread pool, thread is cached up and used repeatedly. Transmitting value from parent thread to child thread has no meaning. Application need transmit value from the time task is created to the time task is executed.

If you have problem or question, please submit Issue or play fork and pull request dance.

🎨 Requirements

The Requirements listed below is also why I sort out TransmittableThreadLocal in my work.

  • Application container or high layer framework transmit information to low layer sdk.
  • Transmit context to logging without application code aware.

👥 User Guide

1. Simple usage

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

// =====================================================

// set in parent thread
context.set("value-set-in-parent");

// =====================================================

// read in child thread, value is "value-set-in-parent"
String value = context.get();

# See the executable demo SimpleDemo.kt with full source code.

This is the function of class InheritableThreadLocal, should use class InheritableThreadLocal instead.

But when use thread pool, thread is cached up and used repeatedly. Transmitting value from parent thread to child thread has no meaning. Application need transmit value from the time task is created to the point task is executed.

The solution is below usage.

2. Transmit value even using thread pool

2.1 Decorate Runnable and Callable

Decorate input Runnable and Callable by TtlRunnable and TtlCallable.

Sample code:

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

// =====================================================

// set in parent thread
context("value-set-in-parent");

Runnable task = new RunnableTask();
// extra work, create decorated ttlRunnable object
Runnable ttlRunnable = TtlRunnable.get(task);
executorService.submit(ttlRunnable);

// =====================================================

// read in task, value is "value-set-in-parent"
String value = context.get();

NOTE
Even when the same Runnable task is submitted to the thread pool multiple times, the decoration operation (ie: TtlRunnable.get(task)) is required for each submission to capture the value of the TransmittableThreadLocal context at submission time; That is, if the same task is submitted next time without reperforming decoration and still using the last TtlRunnable, the submitted task will run in the context of the last captured context. The sample code is as follows:

// first submission
Runnable task = new RunnableTask();
executorService.submit(TtlRunnable.get(task));

// ... some biz logic,
// and modified TransmittableThreadLocal context ...
// context.set("value-modified-in-parent");

// next submission
// reperform decoration to transmit the modified TransmittableThreadLocal context
executorService.submit(TtlRunnable.get(task));

Above code show how to dealing with Runnable, Callable is similar:

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

// =====================================================

// set in parent thread
context.set("value-set-in-parent");

Callable call = new CallableTask();
// extra work, create decorated ttlCallable object
Callable ttlCallable = TtlCallable.get(call);
executorService.submit(ttlCallable);

// =====================================================

// read in call, value is "value-set-in-parent"
String value = context.get();

# See the executable demo TtlWrapperDemo.kt with full source code.

2.2 Decorate thread pool

Eliminating the work of Runnable and Callable Decoration every time it is submitted to thread pool. This work can be completed in the thread pool.

Use util class com.alibaba.ttl.threadpool.TtlExecutors to decorate thread pool.

Util class com.alibaba.ttl.threadpool.TtlExecutors has below methods:

  • getTtlExecutor: decorate interface Executor
  • getTtlExecutorService: decorate interface ExecutorService
  • getTtlScheduledExecutorService: decorate interface ScheduledExecutorService

Sample code:

ExecutorService executorService = ...
// extra work, create decorated executorService object
executorService = TtlExecutors.getTtlExecutorService(executorService);

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

// =====================================================

// set in parent thread
context.set("value-set-in-parent");

Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);

// =====================================================

// read in Task or Callable, value is "value-set-in-parent"
String value = context.get();

# See the executable demo TtlExecutorWrapperDemo.kt with full source code.

2.3 Use Java Agent to decorate thread pool implementation class

In this usage, transmission is transparent(no decoration operation).

Sample code:

// ## 1. upper layer logic of framework ##
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
context.set("value-set-in-parent");

// ## 2. biz logic ##
ExecutorService executorService = Executors.newFixedThreadPool(3);

Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);

// ## 3. underlayer logic of framework ##
// read in Task or Callable, value is "value-set-in-parent"
String value = context.get();

# See the executable demo AgentDemo.kt with full source code, run demo by the script scripts/run-agent-demo.sh.

At present, TTL agent has decorated below JDK execution components(aka. thread pool) implementation:

  • java.util.concurrent.ThreadPoolExecutor and java.util.concurrent.ScheduledThreadPoolExecutor
  • java.util.concurrent.ForkJoinTask(corresponding execution component is java.util.concurrent.ForkJoinPool
    • decoration implementation code is in ForkJoinTtlTransformlet.java, supports since version 2.5.1.
    • NOTE: CompletableFuture and (parallel) Stream introduced in Java 8 is executed through ForkJoinPool underneath, so after supporting ForkJoinPool, TTL also supports CompletableFuture and Stream transparently. 🎉
  • java.util.TimerTask(corresponding execution component is java.util.Timer
    • decoration implementation code is in TimerTaskTtlTransformlet.java, supports since version 2.7.0.
    • NOTE: Since version 2.11.2 decoration for TimerTask default is enable (because correctness is first concern, not the best practice like "It is not recommended to use TimerTask" :); before version 2.11.1 default is disable.
    • enabled/disable by agent argument ttl.agent.enable.timer.task:
      • -javaagent:path/to/transmittable-thread-local-2.x.y.jar=ttl.agent.enable.timer.task:true
      • -javaagent:path/to/transmittable-thread-local-2.x.y.jar=ttl.agent.enable.timer.task:false
    • more info about TTL agent arguments, see the javadoc of TtlAgent.java.

Add start options on Java command:

  • -javaagent:path/to/transmittable-thread-local-2.x.y.jar

Java command example:

java -javaagent:transmittable-thread-local-2.x.y.jar \
    -cp classes \
    com.alibaba.demo.ttl.agent.AgentDemo

# if changed the TTL jar file name or the TTL version is before 2.6.0,
# should set argument -Xbootclasspath explicitly.
java -javaagent:path/to/ttl-foo-name-changed.jar \
    -Xbootclasspath/a:path/to/ttl-foo-name-changed.jar \
    -cp classes \
    com.alibaba.demo.ttl.agent.AgentDemo

java -javaagent:path/to/transmittable-thread-local-2.5.1.jar \
    -Xbootclasspath/a:path/to/transmittable-thread-local-2.5.1.jar \
    -cp classes \
    com.alibaba.demo.ttl.agent.AgentDemo

Run the script scripts/run-agent-demo.sh to start demo of "Use Java Agent to decorate thread pool implementation class".

NOTE

  • Because TTL agent modified the JDK std lib classes, make code refer from std lib class to the TTL classes, so the TTL Agent jar must be added to boot classpath.
  • Since v2.6.0, TTL agent jar will auto add self to boot classpath. But you should NOT modify the downloaded TTL jar file name in the maven repo(eg: transmittable-thread-local-2.x.y.jar).
    • if you modified the downloaded TTL jar file name(eg: ttl-foo-name-changed.jar), you must add TTL agent jar to boot classpath manually by java option -Xbootclasspath/a:path/to/ttl-foo-name-changed.jar.

The implementation of auto adding self agent jar to boot classpath use the Boot-Class-Path property of manifest file(META-INF/MANIFEST.MF) in the TTL Java Agent Jar:

Boot-Class-Path

A list of paths to be searched by the bootstrap class loader. Paths represent directories or libraries (commonly referred to as JAR or zip libraries on many platforms). These paths are searched by the bootstrap class loader after the platform specific mechanisms of locating a class have failed. Paths are searched in the order listed.

More info:

🔌 Java API Docs

The current version Java API documentation: https://alibaba.github.io/transmittable-thread-local/apidocs/

🍪 Maven Dependency

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.12.3</version>
</dependency>

Check available version at search.maven.org.

🔨 About compilation, build and dev

How to compile and build

Compilation/build environment require JDK 8~11; Compilation can be performed in the normal way of Maven.

# The project already contains Maven that satisfied the required version, directly run mvnw in the project root directory; there is no need to manually install Maven by yourself.

# Run test case
./mvnw test
# Compile and package
./mvnw package
# Run test case, compile and package, install TTL library to local Maven
./mvnw install

##################################################
# If you use maven installed by yourself, the version requirement: maven 3.3.9+

mvn install

How to development by IDE

If you use IDE to develop (such as IntelliJ IDEA), note that: open the pom4ide.xml file in the root directory of the project instead of pom.xml via IDE; To avoid IDE complain using JDK 8 standard library classes not found.

The reason that IDE support is not good / have to change a POM file, is:
The code implementation of TTL uses the JDK 8 standard library class, but it is compiled into a Java 6 version class files.

🗿 More Documentation

📚 Related Resources

JDK Core Classes

💝 Who used

Some open-source projects used TTL:

  • Middleware
  • Middleware/Data
    • ppdaicorp/das
      数据库访问框架(data access service),包括数据库控制台das console,数据库客户端das client和数据库服务端das server三部分
    • SimonAlong/Neo
      Orm框架:基于ActiveRecord思想开发的至简化且功能很全的Orm框架
    • didi/ALITA
      a layer-based data analysis tool
    • didi/daedalus
      实现快速创建数据构造流程,数据构造流程的可视化、线上化、持久化、标准化
    • DataLinkDC/DataLink
      a new open source solution to bring Flink development to data center
  • Middleware/Flow engine
  • Middleware/Log
    • dromara/TLog star
      Lightweight distributed log label tracking framework
    • fayechenlong/plumelog star
      一个java分布式日志组件,支持百亿级别
    • minbox-projects/minbox-logging star
      分布式零侵入式、链路式请求日志分析框架。提供Admin端点进行采集日志、分析日志、日志告警通知、服务性能分析等。通过Admin Ui可查看实时链路日志信息、在线业务服务列表
      • minbox-projects/bulldog star
        一款分布式链路日志跟踪监控框架,支持Openfeign、RestTemplate、Retrofit、HttpClient、OkHttp、RabbitMQ等方式透传链路信息
      • minbox-projects/api-boot star
        为接口服务而生的,基于“ SpringBoot”完成扩展和自动配置,内部封装了一系列的开箱即用Starters
    • ofpay/logback-mdc-ttl
      logback扩展,集成transmittable-thread-local支持跨线程池的mdc跟踪
    • oldratlee/log4j2-ttl-thread-context-map
      Log4j2 TTL ThreadContextMap, Log4j2 extension integrated TransmittableThreadLocal to MDC
  • Middleware/Bytecode
  • Test solution or tool
    • alibaba/jvm-sandbox-repeater
      A Java server-side recording and playback solution based on JVM-Sandbox, 录制/回放通用解决方案
    • alibaba/testable-mock
      换种思路写Mock,让单元测试更简单
    • shulieTech/Takin
      measure online environmental performance test for full-links, Especially for microservices
      • shulieTech/LinkAgent
        a Java-based open-source agent designed to collect data and control Functions for Java applications through JVM bytecode, without modifying applications codes
    • alibaba/virtual-environment
      Route isolation with service sharing, 阿里测试环境服务隔离和联调机制的Kubernetes版实现
  • Tool product
    • ssssssss-team/spider-flow star
      新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫
    • nekolr/slime
      🍰 一个可视化的爬虫平台
    • zjcscut/octopus
      长链接压缩为短链接的服务
    • xggz/mqr star
      茉莉QQ机器人(简称MQR),采用mirai的Android协议实现的QQ机器人服务,通过web控制机器人的启停和配置
  • Business service or platform application
    • OpenBankProject/OBP-API
      An open source RESTful API platform for banks that supports Open Banking, XS2A and PSD2 through access to accounts, transactions, counterparties, payments, entitlements and metadata - plus a host of internal banking and management APIs
    • Joolun/JooLun-wx star
      JooLun微信商城
    • tengshe789/SpringCloud-miaosha
      一个基于spring cloud Greenwich的简单秒杀电子商城项目
  • Spring Cloud microservices framework solution
    • zlt2000/microservices-platform star
      基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离的企业级微服务多租户系统架构
    • zuihou/lamp-cloud star
      基于Jdk11 + SpringCloud + SpringBoot 的微服务快速开发平台,其中的可配置的SaaS功能尤其闪耀, 具备RBAC功能、网关统一鉴权、Xss防跨站攻击、自动代码生成、多种存储系统、分布式事务、分布式定时任务等多个模块,支持多业务系统并行开发, 支持多服务并行开发,可以作为后端服务的开发脚手架
      • zuihou/lamp-util star
        打造一套兼顾 SpringBoot 和 SpringCloud 项目的公共工具类
    • gavenwangcn/vole
      SpringCloud Micro service business framework, SpringCloud 微服务商业脚手架
    • liuweijw/fw-cloud-framework star
      基于springcloud全家桶开发分布式框架(支持oauth2认证授权、SSO登录、统一下单、微信公众号服务、Shardingdbc分库分表、常见服务监控、链路监控、异步日志、redis缓存等功能),实现基于Vue全家桶等前后端分离项目工程
    • matevip/matecloud star
      一款基于Spring Cloud Alibaba的微服务架构
    • liuht777/Taroco
      整合Nacos、Spring Cloud Alibaba,提供了一系列starter组件, 同时提供服务治理、服务监控、OAuth2权限认证,支持服务降级/熔断、服务权重
    • yzcheng90/ms
      一个前后分离的分布式 spring cloud 框架(全家桶),这里有统一认证,统一网关等等功能,是一个非常简洁的微服务脚手架
    • fafeidou/fast-cloud-nacos
      致力于打造一个基于nacos为注册中心,结合企业开发习惯,总结的一些基本的实现方式
    • HongZhaoHua/jstarcraft-core
      目标是提供一个通用的Java核心编程框架,作为搭建其它框架或者项目的基础. 让相关领域的研发人员能够专注高层设计而不用关注底层实现. 涵盖了缓存,编解码,通讯,事件,输入/输出,监控,存储,配置,脚本和事务10个方面
    • budwk/budwk star
      BudWk 原名 NutzWk star,基于国产框架 nutz 及 nutzboot 开发的开源Web基础项目,集权限体系、系统参数、数据字典、站内消息、定时任务、CMS、微信等最常用功能,不庞杂、不面面俱到,使其具有上手容易、开发便捷、扩展灵活等特性,特别适合各类大中小型定制化项目需求
    • yinjihuan/spring-cloud
      《Spring Cloud微服务-全栈技术与案例解析》和《Spring Cloud微服务 入门 实战与进阶》配套源码

more open-source projects used TTL, see user repos

👷 Contributors

  • Jerry Lee <oldratlee at gmail dot com> @oldratlee
  • Yang Fang <snoop.fy at gmail dot com> @driventokill
  • Zava Xu <zava.kid at gmail dot com> @zavakid
  • wuwen <wuwen.55 at aliyun dot com> @wuwen5
  • Xiaowei Shi <179969622 at qq dot com> @xwshiustc
  • David Dai <351450944 at qq dot com> @LNAmp
  • Your name here :-)

GitHub Contributors