🚧 这个分支是TransmittableThreadLocal(TTL) v3,在开�?�ä¸è¿˜æ²¡æœ‰ï¿½?�布。
v3的版本说明�?工作项列表�?�其进展,�?��? issue 432。
👉 目�?使用ä¸çš„稳定�?�布版本v2.x在 分支2.x上。
🔧 功能🎨 需求场景👥 User Guide🔌 Java API Docs�?� Maven�?赖🔨 关于编译构建�?� FAQ✨ 使用TTL的好处与必�?性🗿 更多文档📚 相关资料💗 Who Used👷 Contributors
🔧 功能
TransmittableThreadLocal(TTL)ï¼šåœ¨ä½¿ç”¨çº¿ç¨‹æ± ç‰ä¼šæ± 化�?用线程的执行组件情况下,�??ä¾›ThreadLocalå€¼çš„ä¼ é€’åŠŸèƒ½ï¼Œè§£å†³å¼‚æ¥æ‰§è¡Œæ—¶ä¸Šä¸‹æ–‡ä¼ 递的问题。一个Javaæ ‡å‡†åº“æœ¬åº”ä¸ºæ¡†æž¶/ä¸é—´ä»¶è®¾æ–½å¼€ï¿½?��??ä¾›çš„æ ‡ï¿½?能力,本库功能�?�焦 & 0�?赖,支�?Java 6~20。
JDKçš„InheritableThreadLocal类�?�以完�?父线程到�?çº¿ç¨‹çš„å€¼ä¼ é€’ã€‚ä½†å¯¹äºŽä½¿ç”¨çº¿ç¨‹æ± ç‰ä¼šæ± 化�?ç”¨çº¿ç¨‹çš„æ‰§è¡Œç»„ä»¶çš„æƒ…å†µï¼Œçº¿ç¨‹ç”±çº¿ç¨‹æ± åˆ›å»ºå¥½ï¼Œå¹¶ä¸”çº¿ç¨‹æ˜¯æ± åŒ–èµ·ï¿½?��??�?使用的;这时父�?线程关系的ThreadLocalå€¼ä¼ é€’å·²ï¿½?没有�?义,应用需�?的实际上是把 任务�??äº¤ç»™çº¿ç¨‹æ± æ—¶çš„ThreadLocalå€¼ä¼ é€’åˆ° 任务执行时。
本库�??供的TransmittableThreadLocalç±»ç»§æ‰¿å¹¶åŠ å¼ºInheritableThreadLocal类,解决上述的问题,使用详�? User Guide。
整个TransmittableThreadLocalåº“çš„æ ¸å¿ƒåŠŸèƒ½ï¼ˆç”¨æˆ·API�?çº¿ç¨‹æ± ExecutorService/ForkJoinPool/TimerTask�?�其线程工厂的Wrapper;开�?�者API�?框架/ä¸é—´ä»¶çš„集�?API),�?�有 ~1000 SLOC代�?行,�?�常精�?。
欢迎
- 建议和�??问,�??交 Issue
- 贡献和改进,Fork �?��??通过 Pull Request 贡献代�?
从
TTL v2.13+开始,�?�级到Java 8。
如果需�?Java 6的支�?,使用版本2.12.x
🎨 需求场景
ThreadLocal的需求场景�?�TransmittableThreadLocalçš„æ½œåœ¨éœ€æ±‚åœºæ™¯ï¼Œå¦‚æžœä½ çš„ä¸šåŠ¡éœ€ï¿½?ã€Žåœ¨ä½¿ç”¨çº¿ç¨‹æ± ç‰ä¼šæ± 化�?ç”¨çº¿ç¨‹çš„æ‰§è¡Œç»„ä»¶æƒ…å†µä¸‹ä¼ é€’ThreadLocal值�?则是TransmittableThreadLocalç›®æ ‡åœºæ™¯ã€‚
下�?ï¿½æ˜¯å‡ ä¸ªå…¸åž‹åœºæ™¯ä¾‹ï¿½?。
- 分布�?跟踪系统 或 全链路压测(�?ï¿½é“¾è·¯æ‰“æ ‡ï¼‰
- 日志收集记录系统上下文
Session级Cache- 应用容器或上层框架跨应用代�?给下层
SDKä¼ é€’ä¿¡ï¿½?�
�?�个场景的展开说明�?��?�?文档 需求场景。
👥 User Guide
使用类TransmittableThreadLocal�?��?å˜å€¼ï¼Œå¹¶è·¨çº¿ç¨‹æ± ä¼ é€’ã€‚
TransmittableThreadLocal继承InheritableThreadLocal,使用方�?也类似。相比InheritableThreadLocalï¼Œæ·»åŠ äº†protectedçš„transmitteeValue()方法,用于定制 任务�??äº¤ç»™çº¿ç¨‹æ± æ—¶ çš„ThreadLocalå€¼ä¼ é€’åˆ° 任务执行时 çš„ä¼ é€’æ–¹ï¿½?,缺�?是简�?ï¿½çš„èµ‹å€¼ä¼ é€’ã€‚
注�?ï¼šå¦‚æžœä¼ é€’çš„å¯¹è±¡ï¼ˆå¼•ç”¨ç±»åž‹ï¼‰ä¼šè¢«ä¿®æ”¹ï¼Œä¸”æ²¡æœ‰ï¿½?�深拷�?ï¼ˆå¦‚ç›´æŽ¥ä¼ é€’å¼•ç”¨æˆ–æ˜¯æµ…æ‹·ï¿½?),那么
- å› ä¸ºè·¨çº¿ç¨‹ä¼ é€’è€Œï¿½?�?有线程�?é—ï¼Œä¼ é€’å¯¹è±¡åœ¨å¤šä¸ªçº¿ç¨‹ä¹‹é—´æ˜¯æœ‰å…±äº«çš„ã€‚
- 与
JDKçš„InheritableThreadLocal.childValue()ä¸€æ ·ï¼Œéœ€ï¿½?使用者/业务逻辑注�?�?�?ä¼ é€’å¯¹è±¡çš„çº¿ç¨‹å®‰å…¨ã€‚
关于
transmitteeValue方法 的 展开说明
关于构�?�?�缀
er与ee的说明:
transmit是动�?ä¼ é€’ï¼Œtransmitter动作的执行者/主动方,而transmittee动作的接收者/被动方。er与ee�?�缀的常�?�?是employer(雇主)/employee(雇员)�?caller(调用者)/callee(被调用者)。
具体使用方�?�?下�?�的说明。
1. 简�?�使用
父线程给�?çº¿ç¨‹ä¼ é€’å€¼ã€‚
示例代�?:
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// 在父线程ä¸è®¾ç½®
context.set("value-set-in-parent");
// =====================================================
// 在�?线程ä¸ï¿½?�以读�?�,值是"value-set-in-parent"
String value = context.get();# 完整�?��?行的Demo代�?�?��?SimpleDemo.kt。
这其实是InheritableThreadLocal的功能,应该使用InheritableThreadLocal�?�完�?。
ä½†å¯¹äºŽä½¿ç”¨çº¿ç¨‹æ± ç‰ä¼šæ± 化�?ç”¨çº¿ç¨‹çš„æ‰§è¡Œç»„ä»¶çš„æƒ…å†µï¼Œçº¿ç¨‹ç”±çº¿ç¨‹æ± åˆ›å»ºå¥½ï¼Œå¹¶ä¸”çº¿ç¨‹æ˜¯æ± åŒ–èµ·ï¿½?��??�?使用的;这时父�?线程关系的ThreadLocalå€¼ä¼ é€’å·²ï¿½?没有�?义,应用需�?的实际上是把 任务�??äº¤ç»™çº¿ç¨‹æ± æ—¶çš„ThreadLocalå€¼ä¼ é€’åˆ° 任务执行时。
解决方法�?��?下�?ï¿½çš„è¿™å‡ ï¿½?用法。
2. �?�?çº¿ç¨‹æ± ä¸ä¼ 递值
2.1 修饰Runnable和Callable
使用TtlRunnableå’ŒTtlCallable�?ï¿½ä¿®é¥°ä¼ å…¥çº¿ç¨‹æ± çš„Runnableå’ŒCallable。
示例代�?:
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// 在父线程ä¸è®¾ç½®
context.set("value-set-in-parent");
Runnable task = new RunnableTask();
// �?外的处�?�,生�?修饰了的对象ttlRunnable
Runnable ttlRunnable = TtlRunnable.get(task);
executorService.submit(ttlRunnable);
// =====================================================
// Taskä¸ï¿½?�以读�?�,值是"value-set-in-parent"
String value = context.get();注�?:
�?�使是�?�一个Runnable任务多次�??äº¤åˆ°çº¿ç¨‹æ± æ—¶ï¼Œï¿½?次�??交时都需�?通过修饰�?作(�?�TtlRunnable.get(task))以抓�?�这次�??交时的TransmittableThreadLocal上下文的值;�?�如果�?�一个任务下一次�??交时�?执行修饰而�?然使用上一次的TtlRunnable,则�??交的任务�?行时会是之�?修饰�?作所抓�?�的上下文。示例代�?如下:
// 第一次�??交
Runnable task = new RunnableTask();
executorService.submit(TtlRunnable.get(task));
// ...业务逻辑代�?,
// 并且修改了 TransmittableThreadLocal上下文 ...
context.set("value-modified-in-parent");
// �?次�??交
// �?æ–°æ‰§è¡Œä¿®é¥°ï¼Œä»¥ä¼ é€’ä¿®æ”¹äº†çš„ TransmittableThreadLocal上下文
executorService.submit(TtlRunnable.get(task));上�?�演示了Runnable,Callable的处�?�类似
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// 在父线程ä¸è®¾ç½®
context.set("value-set-in-parent");
Callable call = new CallableTask();
// �?外的处�?�,生�?修饰了的对象ttlCallable
Callable ttlCallable = TtlCallable.get(call);
executorService.submit(ttlCallable);
// =====================================================
// Callä¸ï¿½?�以读�?�,值是"value-set-in-parent"
String value = context.get();# 完整�?��?行的Demo代�?�?��?TtlWrapperDemo.kt。
整个过程的完整时�?图
2.2 修饰线程æ±
�?去�?次Runnableå’ŒCallableä¼ å…¥çº¿ç¨‹æ± æ—¶çš„ä¿®é¥°ï¼Œè¿™ä¸ªé€»è¾‘ï¿½?ï¿½ä»¥åœ¨çº¿ç¨‹æ± ä¸å®Œï¿½?。
通过工具类TtlExecutors完�?,有下�?�的方法:
getTtlExecutor:修饰接�?�ExecutorgetTtlExecutorService:修饰接�?�ExecutorServicegetTtlScheduledExecutorService:修饰接�?�ScheduledExecutorService
示例代�?:
ExecutorService executorService = ...
// �?外的处�?�,生�?修饰了的对象executorService
executorService = TtlExecutors.getTtlExecutorService(executorService);
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// 在父线程ä¸è®¾ç½®
context.set("value-set-in-parent");
Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);
// =====================================================
// Task或是Callä¸ï¿½?�以读�?�,值是"value-set-in-parent"
String value = context.get();# 完整�?��?行的Demo代�?�?��?TtlExecutorWrapperDemo.kt。
2.3 使用Java Agent�?�修饰JDKçº¿ç¨‹æ± å®žçŽ°ç±»
这�?方�?ï¼Œå®žçŽ°çº¿ç¨‹æ± çš„ä¼ é€’æ˜¯ï¿½?明的,业务代�?䏿²¡æœ‰ä¿®é¥°Runnableæˆ–æ˜¯çº¿ç¨‹æ± çš„ä»£ï¿½?。�?��?�以�?�到应用代�? æ— ä¾µå…¥ã€‚
# 关于 æ— ä¾µå…¥ 的更多说明�?��?文档Java Agent方�?对应用代�?æ— ä¾µå…¥ã€‚
示例代�?:
// ## 1. 框架上层逻辑,�?�ç»ï¿½?程框架调用业务 ##
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
context.set("value-set-in-parent");
// ## 2. 应用逻辑,�?�ç»ï¿½?程业务调用框架下层逻辑 ##
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);
// ## 3. 框架下层逻辑 ##
// Task或是Callä¸ï¿½?�以读�?�,值是"value-set-in-parent"
String value = context.get();Demo�?��?AgentDemo.kt。执行工程下的脚本scripts/run-agent-demo.sh�?��?��?行Demo。
目�?TTL Agentä¸ï¼Œä¿®é¥°äº†çš„JDK执行器组件(�?ï¿½å¦‚çº¿ç¨‹æ± ï¼‰å¦‚ä¸‹ï¼š
java.util.concurrent.ThreadPoolExecutor和java.util.concurrent.ScheduledThreadPoolExecutor- 修饰实现代�?在
JdkExecutorTtlTransformlet.java。
- 修饰实现代�?在
java.util.concurrent.ForkJoinTask(对应的执行器组件是java.util.concurrent.ForkJoinPool)- 修饰实现代�?在
ForkJoinTtlTransformlet.java。从版本2.5.1开始支�?。 - 注�?:
Java 8引入的CompletableFuture与(并行执行的)Stream底层是通过ForkJoinPool�?�执行,所以支�?ForkJoinPool�?�,TTL也就�?明支�?了CompletableFuture与Stream。🎉
- 修饰实现代�?在
java.util.TimerTask的�?类(对应的执行器组件是java.util.Timer)- 修饰实现代�?在
TimerTaskTtlTransformlet.java。从版本2.7.0开始支�?。 - 注�?:从
2.11.2版本开始缺�?开�?�TimerTaskçš„ä¿®é¥°ï¼ˆå› ä¸ºï¿½?�?æ£ç¡®æ€§æ˜¯ç¬¬ä¸€ï¿½?,而�?是最佳实践『�?推�??使用TimerTask�?:);2.11.1版本�?�其之�?的版本没有缺�?开�?�TimerTask的修饰。 - 使用
Agent�?�数ttl.agent.enable.timer.task开�?�/å…³é—TimerTask的修饰:-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
- 更多关于
TTL Agent�?�数的�?置说明详�?TtlAgent.java的JavaDoc。
- 修饰实现代�?在
关于
java.util.TimerTask/java.util.Timer的 展开说明
Timer是JDK 1.3的�?类,�?推�??使用Timer类。推�??用
ScheduledExecutorService。
ScheduledThreadPoolExecutor实现更强壮,并且功能更丰富。 如支�?�?ç½®çº¿ç¨‹æ± çš„å¤§ï¿½?(Timer�?�有一个线程);Timer在Runnableä¸æŠ›å‡ºå¼‚å¸¸ä¼šä¸æ¢å®šæ—¶æ‰§è¡Œã€‚更多说明�?��? 10. Mandatory Run multiple TimeTask by using ScheduledExecutorService rather than Timer because Timer will kill all running threads in case of failing to catch exceptions. - Alibaba Java Coding Guidelines。
Java Agent的�?�动�?�数�?置
在Java的�?�动�?ï¿½æ•°åŠ ä¸Šï¼š-javaagent:path/to/transmittable-thread-local-2.x.y.jar。
注�?:
- 如果修改了下载的
TTL的Jar的文件�??(transmittable-thread-local-2.x.y.jar),则需�?自己手动通过-Xbootclasspath JVM�?�数�?�显�?�?置。
比如修改文件�??�?ttl-foo-name-changed.jar,则还需�?åŠ ä¸ŠJava的�?�动�?�数:-Xbootclasspath/a:path/to/ttl-foo-name-changed.jar。 - 或使用
v2.6.0之�?的版本(如v2.5.1),则也需�?自己手动通过-Xbootclasspath JVM�?�数�?�显�?�?置(就�?TTL之�?的版本的�?ï¿½æ³•ä¸€æ ·ï¼‰ã€‚
åŠ ä¸ŠJava的�?�动�?�数:-Xbootclasspath/a:path/to/transmittable-thread-local-2.5.1.jar。
Java命令行示例如下:
java -javaagent:path/to/transmittable-thread-local-2.x.y.jar \
-cp classes \
com.alibaba.demo.ttl.agent.AgentDemo
# 如果修改了TTL jar文件�?? 或 TTL版本是 2.6.0 之�?
# 则还需�?显�?设置 -Xbootclasspath �?�数
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关于
boot class path的 展开说明
å› ä¸ºä¿®é¥°äº†
JDKæ ‡å‡†åº“çš„ç±»ï¼Œæ ‡å‡†åº“ç”±bootstrap class loaderåŠ è½½ï¼›ä¿®é¥°ï¿½?�的JDK类引用了TTL的代�?,所以Java Agent使用方�?下TTL Jar文件需�?�?置到boot class path上。
TTL从v2.6.0å¼€å§‹ï¼ŒåŠ è½½TTL Agent时会自动设置TTL Jar到boot class path上。
注�?:�?能修改从Maven库下载的TTL Jar文件�??(形如transmittable-thread-local-2.x.y.jar)。 如果修改了,则需�?自己手动通过-Xbootclasspath JVM�?�数�?�显�?�?置(就�?TTL之�?的版本的�?ï¿½æ³•ä¸€æ ·ï¼‰ã€‚è‡ªåŠ¨è®¾ç½®
TTL Jar到boot class path的实现是通过指定TTL Java Agent Jar文件里manifest文件(META-INF/MANIFEST.MF)的Boot-Class-Path属性:
Boot-Class-PathA 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.
更多详�?
🔌 Java API Docs
当�?版本的Java API文档地�?�: https://alibaba.github.io/transmittable-thread-local/apidocs/
�?� Maven�?赖
示例:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.2</version>
</dependency>�?�以在 search.maven.org 查看�?�用的版本。
🔨 关于编译构建
编译构建的环境�?求: JDK 8+;用Maven常规的方�?执行编译构建�?��?�:
# 在工程ä¸å·²ï¿½?包�?�了符�?�版本�?求的Maven,直接�?行 å·¥ç¨‹æ ¹ç›®å½•ä¸‹çš„mvnw;并�?需�?先手动自己安装好Maven。
# �?行测试Case
./mvnw test
# 编译打包
./mvnw package
# �?行测试Case�?编译打包�?安装TTL库到Maven本地
./mvnw install
#####################################################
# å¦‚æžœä½¿ç”¨ä½ è‡ªå·±å®‰è£…çš„ maven,版本�?求:maven 3.3.9+
mvn install�?� FAQ
Q1. TTL Agent与其它Agent(如Skywalking�?Promethues)�?�?�使用时�?生效?
�?置TTL Agent在最�?的�?置,�?�以�?��?与其它其它Agent�?�?�使用时,TTL Agent�?�能的�?生效问题。�?置示例:
java -javaagent:path/to/transmittable-thread-local-2.x.y.jar \
-javaagent:path/to/skywalking-agent.jar \
-jar your-app.jaråŽŸå› æ˜¯ï¼š
- �?
Skywalkingè¿™æ ·çš„Agent的入�?�逻辑(premain)包�?ï¿½äº†çº¿ç¨‹æ± çš„ï¿½?�动。 - 如果�?ç½®åœ¨è¿™æ ·çš„
Agent�?置在�?�?�,到了TTL Agent(的premain)时,TTL需�?åŠ å¼ºçš„çº¿ç¨‹æ± ç±»å·²ï¿½?åŠ è½½ï¼ˆload)了。 TTL Agentçš„TtlTransformeræ˜¯åœ¨ç±»åŠ è½½æ—¶è§¦ï¿½?�类的增强;如果类已�?åŠ è½½äº†ä¼šè·³è¿‡TTL Agent的增强逻辑。
更多讨论�?��? Issue:TTL agent与其他Agent的兼容性问题 #226。
Q2. MacOS下,使用Java Agent,�?�能会报JavaLaunchHelper的出错信�?�
JDK Bug: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8021205
�?�以�?�一个版本的JDK。我的开�?�机上1.7.0_40有这个问题,1.6.0_51�?1.7.0_45�?�以�?行。
# 1.7.0_45还是有JavaLaunchHelper的出错信�?�,但�?影�?�?行。
✨ 使用TTL的好处与必�?性
注:�?读这一节,并�?会影�?ä½ ä½¿ç”¨
TTL�?ï¿½è§£å†³ä½ ç¢°åˆ°çš„é—®é¢˜ï¼Œï¿½?�以放心跳过;读了 User Guide 就�?�以快速用起�?�了~😄 这一节信�?�密度较高�?易读。
好处:�?明且自动完�?æ‰€æœ‰å¼‚æ¥æ‰§è¡Œä¸Šä¸‹æ–‡çš„�?�定制�?规范化的�?��?ï¿½ä¸Žä¼ é€’ã€‚
这个好处也是TransmittableThreadLocalçš„ç›®æ ‡ã€‚
必�?性:�?�?�应用的分布�?微�?务化并使用�?��?ä¸é—´ä»¶ï¼Œè¶Šï¿½?�越多的功能与组件会涉�?��?�?�的上下文,逻辑�?程也越�?�越长;上下文问题实际上是个大的易错的架构问题,需�?统一的对业务�?明的解决方案。
使用ThreadLocalä½œä¸ºä¸šåŠ¡ä¸Šä¸‹æ–‡ä¼ é€’çš„ï¿½?典技术手段在ä¸é—´ä»¶ï¿½?技术与业务框架ä¸å¹¿æ³›å¤§ï¿½?ä½¿ç”¨ã€‚è€Œå¯¹äºŽç”Ÿäº§åº”ç”¨ï¼Œå‡ ä¹Žä¸€å®šä¼šä½¿ç”¨çº¿ç¨‹æ± ç‰å¼‚æ¥æ‰§è¡Œç»„件,以高效支撑线上大�?�?。但使用ThreadLocal�?�其set/removeçš„ä¸Šä¸‹æ–‡ä¼ é€’æ¨¡ï¿½?ï¼Œåœ¨ä½¿ç”¨çº¿ç¨‹æ± ç‰å¼‚æ¥æ‰§è¡Œç»„件时,å˜åœ¨å¤šæ–¹ï¿½?�的问题:
1. 从业务使用者角度�?�看
- �?�??
- 业务逻辑�?知�?�:有哪些上下文;�?�个上下文是如何获�?�的。
- 并需�?业务逻辑去一个一个地�?��?ï¿½ä¸Žä¼ é€’ã€‚
- �?赖
- 需�?直接�?赖�?�?�
ThreadLocal上下文�?�自的获�?�的逻辑或类。 - �?
RPC的上下文(如Dubboçš„RpcContext)�?全链路跟踪的上下文(如SkyWalkingçš„ContextManager)�?�?�?�业务模�?�ä¸çš„业务�?程上下文,ç‰ç‰ã€‚
- 需�?直接�?赖�?�?�
- �?��?(易�?)
- å› ä¸ºï¿½? 事先 知�?�有哪些上下文,如果系统出现了一个新的上下文,业务逻辑就�?ä¿®æ”¹æ·»åŠ ä¸Šæ–°ä¸Šä¸‹æ–‡ä¼ é€’çš„å‡ è¡Œä»£ï¿½?ã€‚ä¹Ÿå°±æ˜¯è¯´å› ç³»ç»Ÿçš„ 上下文新增,业务的 逻辑就跟进�?修改。
- 而对于业务�?�说,�?关心系统的上下文,�?�往往就�?�能�?��?,会是线上故障了。
- �?�?�应用的分布�?微�?务化并使用�?��?ä¸é—´ä»¶ï¼Œè¶Šï¿½?�越多的功能与组件会涉�?��?�?�的上下文,逻辑�?程也越�?�越长;上下文问题实际上是个大的易错的架构问题,需�?统一的对业务�?明的解决方案。
- 定制性
- å› ä¸ºéœ€ï¿½?业务逻辑�?�完�?�?��?ï¿½ä¸Žä¼ é€’ï¼Œä¸šåŠ¡ï¿½?å…³æ³¨ã€Žä¸Šä¸‹æ–‡çš„ä¼ é€’æ–¹ï¿½?�?ï¼šç›´æŽ¥ä¼ å¼•ç”¨ï¼Ÿè¿˜æ˜¯æ‹·ï¿½?ä¼ å€¼ï¼Ÿæ‹·ï¿½?是深拷�?还是浅拷�??在�?�?�的上下文会需�?�?�?�的�?�法。
- ã€Žä¸Šä¸‹æ–‡çš„ä¼ é€’æ–¹ï¿½?�?往往是 上下文的�??供者(或说是业务逻辑的框架部分)�?能决ç–处�?�好的;而 上下文的使用者(或说是业务逻辑的应用部分)往往�?(期望)知�?ï¿½ä¸Šä¸‹æ–‡çš„ä¼ é€’æ–¹ï¿½?。这也�?�以�?�解�?是 �?赖,�?�业务逻辑 �?èµ–/关注/实现了 系统/æž¶æž„çš„ã€Žä¸Šä¸‹æ–‡çš„ä¼ é€’æ–¹ï¿½?�?。
2. 从整体�?程实现角度�?�看
关注的是 ä¸Šä¸‹æ–‡ä¼ é€’ï¿½?ç¨‹çš„è§„èŒƒåŒ–ã€‚ä¸Šä¸‹æ–‡ä¼ é€’åˆ°äº†ï¿½?线程�?�?�好 清�?�(或更准确地说是�? �?��? �?之�?的上下文),需�?业务逻辑去处�?�好。如果业务逻辑对清�?�的处�?��?æ£ç¡®ï¼Œæ¯”如:
- 如果清�?��?作�?了:
- 下一次执行�?�能是上次的,�?�『上下文的 污染/串�?��?,会导致业务逻辑错误。
- 『上下文的 泄�?�?ï¼Œä¼šå¯¼è‡´å†…å˜æ³„�?问题。
- 如果清�?��?作�?�多了,会出现上下文 丢失。
上�?�的问题,在业务开�?�ä¸å¼•�?�的Bug真是屡�?�?鲜 �?æœ¬è´¨åŽŸå› æ˜¯ï¼šThreadLocalçš„set/removeçš„ä¸Šä¸‹æ–‡ä¼ é€’æ¨¡ï¿½? åœ¨ä½¿ç”¨çº¿ç¨‹æ± ç‰å¼‚æ¥æ‰§è¡Œç»„件的情况下�?�?是有效的。常�?的典型例�?:
- å½“çº¿ç¨‹æ± æ»¡äº†ä¸”çº¿ç¨‹æ± çš„
RejectedExecutionHandler使用的是CallerRunsPolicy时,�??äº¤åˆ°çº¿ç¨‹æ± çš„ä»»åŠ¡ä¼šåœ¨ï¿½??交线程ä¸ç›´æŽ¥æ‰§è¡Œï¼ŒThreadLocal.remove�?作清�?��??交线程的上下文导致上下文丢失。 - 类似的,使用
ForkJoinPool(包�?�并行执行Stream与CompletableFuture,底层使用ForkJoinPool)的场景,展开的ForkJoinTask会在任务�??交线程ä¸ç›´æŽ¥æ‰§è¡Œã€‚�?ï¿½æ ·å¯¼è‡´ä¸Šä¸‹æ–‡ä¸¢å¤±ã€‚
æ€Žä¹ˆè®¾è®¡ä¸€ä¸ªã€Žä¸Šä¸‹æ–‡ä¼ é€’ï¿½?程�?方案(�?�上下文的生命周期),以�?�?没有上�?�的问题?
期望:上下文生命周期的�?作从业务逻辑ä¸åˆ†ç¦»å‡ºï¿½?�。业务逻辑�?涉�?�生命周期,就�?会有业务代�?如�?忽清�?�而引�?ï¿½çš„é—®é¢˜äº†ã€‚æ•´ä¸ªä¸Šä¸‹æ–‡çš„ä¼ é€’ï¿½?程或说生命周期�?�以规范化�?:�?��?��?回放和�?��?è¿™3个�?作,�?�CRR(capture/replay/restore)模�?。更多讨论�?��? Issue:能在详细讲解一下replay�?restore的设计�?�念�?�?#201。
总结上�?ï¿½çš„è¯´æ˜Žï¼šåœ¨ç”Ÿäº§åº”ç”¨ï¼ˆå‡ ä¹Žä¸€å®šä¼šä½¿ç”¨çº¿ç¨‹æ± ç‰å¼‚æ¥æ‰§è¡Œç»„件)ä¸ï¼Œä½¿ç”¨ThreadLocal�?�其set/removeçš„ä¸Šä¸‹æ–‡ä¼ é€’æ¨¡ï¿½?å‡ ä¹Žä¸€å®šæ˜¯æœ‰é—®é¢˜çš„ï¼Œï¿½?�是在ç‰ä¸€ä¸ªå‡ºBug的机会。
更多TTL好处与必�?性的展开讨论�?��? Issue:这个库带�?ï¿½æ€Žæ ·çš„å¥½å¤„å’Œä¼˜åŠ¿ï¼Ÿ #128,欢迎继ç»è®¨è®º
🗿 更多文档
🎨 需求场景说明�?��? �?伙伴�?�å¦ä»¬å†™çš„TTL使用场景 与 设计实现解�?çš„æ–‡ç« ï¼ˆå†™å¾—éƒ½å¾ˆå¥½ï¿½?) - Issue #123🎓 Developer Guide☔ 性能测试
📚 相关资料
JDK Core Classes
💗 Who Used
使用了TTL的一部分开�?项目:
- ä¸é—´ä»¶
sofastack/sofa-rpc
SOFARPC is a high-performance, high-extensibility, production-level Java RPC frameworkdromara/hmily
Distributed transaction solutionsdromara/gobrs-async
一款功能强大�?�?置�?�活�?带有全链路异常回调�?内å˜ä¼˜åŒ–�?异常状�?管�?�于一身的高性能异æ¥ç¼–排框架。为�?业�??供在�?�?�应用场景下动�?任务编排的能力。 针对于�?�?�场景下,异æ¥çº¿ç¨‹ï¿½?�?�性�?任务�?赖性�?异常状�?难控制性dromara/dynamic-tp
轻�?级动�?çº¿ç¨‹æ± ï¼Œå†…ç½®ç›‘æŽ§å‘Šè¦åŠŸèƒ½ï¼Œæ”¯ï¿½?çº¿ç¨‹æ± ä¸Šä¸‹æ–‡ä¼ é€’ï¼ŒåŸºäºŽä¸»ï¿½?�?ç½®ä¸å¿ƒï¼ˆå·²æ”¯ï¿½?Nacos�?Apollo,Zookeeper,�?�通过SPI自定义实现)opengoofy/hippo4j
动�?çº¿ç¨‹æ± æ¡†æž¶ï¼Œé™„å¸¦ç›‘æŽ§æŠ¥è¦åŠŸèƒ½ï¼Œæ”¯ï¿½? JDK�?Tomcat�?Jetty�?Undertow çº¿ç¨‹æ± ï¼›Apache RocketMQ�?Dubbo�?RabbitMQ�?Hystrix 消费ç‰çº¿ç¨‹æ± 。内置两�?使用模�?:轻�?级�?赖�?ç½®ä¸å¿ƒä»¥ï¿½?ï¿½æ— ä¸é—´ä»¶ï¿½?赖版本siaorg/sia-gateway
微�?务路由网关(zuul-plus)huaweicloud/Sermant
Sermant, a proxyless service mesh solution based on JavaagentZTO-Express/zms
ZTO Message Servicelxchinesszz/tomato
一款专门为SpringBoot项目设计的幂ç‰ç»„ä»¶ytyht226/taskflow
一款轻�?�?简�?�易用�?�?��?�活扩展的通用任务编排框架,基于有�?ï¿½æ— çŽ¯å›¾(DAG)的方�?实现,框架�??供了组件�?用�?�?�æ¥/异æ¥ç¼–排�?�?�件判æ–�?分支选择ç‰èƒ½åŠ›ï¼Œï¿½?ï¿½ä»¥æ ¹ï¿½?��?�?�的业务场景对任�?的业务�?程进行编排foldright/cffu
�? Java CompletableFuture Fu, aka. CF-Fu, pronounced "Shifu"; include best practice/traps guide and a tiny sidekick library to improve user experience and reduce misuse.tuya/connector
The connector framework maps cloud APIs to local APIs based on simple configurations and flexible extension mechanisms
- ä¸é—´ä»¶/数�?�处�?�
apache/shardingsphere
Ecosystem to transform any database into a distributed database system, and enhance it with sharding, elastic scaling, encryption features & morebasicai/xtreme1
The Next GEN Platform for Multisensory Training Data. #3D annotation, lidar-camera annotation and image annotation tools are supportedsagframe/sagacity-sqltoy
JavaçœŸæ£æ™ºæ…§çš„ORM框架dromara/stream-query
�?许完全摆脱Mapperçš„mybatis-plus体验;�?�以使用类似“工具类�?è¿™æ ·çš„ï¿½?��?函数进行数�?�库�?作SimonAlong/Neo
Orm框架:基于ActiveRecord�?想开�?�的至简化且功能很全的Orm框架ppdaicorp/das
数�?�库访问框架(data access service),包括数�?�库控制�?�das console,数�?�库客户端das client和数�?�库�?务端das server三部分didi/ALITA
a layer-based data analysis tooldidi/daedalus
实现快速创建数�?ï¿½æž„é€ ï¿½?程,数�?ï¿½æž„é€ ï¿½?程的�?�视化�?线上化�?�?久化�?æ ‡å‡†åŒ–
- ä¸é—´ä»¶/�?程引擎
dromara/liteflow
a lightweight and practical micro-process frameworkalibaba/bulbasaur
A pluggable, scalable process engine
- ä¸é—´ä»¶/日志
dromara/TLog
Lightweight distributed log label tracking frameworkfayechenlong/plumelog
一个java分布�?日志组件,支�?百亿级别minbox-projects/minbox-logging
分布�?零侵入�?�?链路�?请求日志分�?框架。�??ä¾›Admin端点进行采集日志�?分�?日志�?日志告è¦é€šçŸ¥ï¿½?�?务性能分�?ç‰ã€‚通过Admin Ui�?�查看实时链路日志信�?��?在线业务�?务列表minbox-projects/api-boot
为接�?��?务而生的,基于“ 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
- ä¸é—´ä»¶/å—节�?
ymm-tech/easy-byte-coder
Easy-byte-coder is a non-invasive bytecode injection framework based on JVM
- 业务�?务或平�?�应用
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 APIsgz-yami/mall4j
电商商城 java电商商城系统 uniapp商城 多用户商城Joolun/JooLun-wx
JooLun微信商城HummerRisk/HummerRisk
云原生安全平�?�,包括混�?�云安全治�?�和容器云安全检测XiaoMi/mone
Mone以微�?åŠ¡ä¸ºæ ¸å¿ƒçš„ä¸€ç«™ï¿½?�?业�??�?ï¿½ç ”ï¿½?�平�?�。支�?公共云�?专有云和混�?�云多�?部署形�?;�??供从“项目创建->开�?�->部署->治�?�->应用观测�?ç«¯åˆ°ç«¯çš„ç ”ï¿½?�全�?程�?åŠ¡ï¼›é€šè¿‡äº‘åŽŸç”Ÿæ–°æŠ€æœ¯å’Œç ”ï¿½?�新模�?ï¼Œæ‰“é€ â€œï¿½?��?�?,�?�?ï¿½ç ”ï¿½?�和�?�?�组织,�?障�?ç±³-ä¸å›½åŒºé«˜ï¿½?�?�业务�?大规模团队的�?�?ï¿½ç ”ï¿½?��??�?�,实现多�?效能�??�?�。yangzongzhuan/RuoYi-Cloud
基于Spring Boot�?Spring Cloud & Alibaba的分布�?微�?务架构�?��?管�?�系统somowhere/albedo
基于 Spring Boot �?Spring Security�?Mybatis 的RBAC�?��?管�?�系统qwdigital/LinkWechat
基于�?业微信的开�? SCRM 系统,采用主�?的 Java 微�?务架构,是�?业�?域�?�?管�?�与�?�销的综�?�解决方案,助力�?业�??高客户�?�?�效率,强化�?�销能力,拓展盈利空间hiparker/opsli-boot
一款的低代�?快速平�?�,零代�?开�?�,致力于�?�更简�?的�?��?�管�?�系统topiam/eiam
EIAM(Employee Identity and Access Management Program)�?业级开�?IAM平�?�,实现用户全生命周期的管�?��?统一认�?和�?�点登录�?为数å—身份安全赋能Newspiral/newspiral-business
�?�盟区�?�链底层平�?�
- 工具产�?
ssssssss-team/spider-flow
新一代爬虫平�?�,以图形化方�?定义爬虫�?程,�?写代�?�?��?�完�?爬虫nekolr/slime
�?� 一个�?�视化的爬虫平�?�Jackson0714/PassJava-Platform
一款�?�试刷题的 Spring Cloud 开�?系统。零碎时间利用�?程�?查看常�?�?�试题,夯实Java基础。 该项目�?ï¿½ä»¥æ•™ä¼šä½ å¦‚ä½•ï¿½?�建SpringBoot项目,Spring Cloud项目。 采用�?行的技术,如 SpringBoot�?MyBatis�?Redis�? MySql�? MongoDB�? RabbitMQ�?Elasticsearch,采用Docker容器化部署martin-chips/DimpleBlog
基于SpringBoot2�?�建的个人�?�客系统zjcscut/octopus
长链接压缩为çŸé“¾æŽ¥çš„�?务xggz/mqr
茉莉QQ机器人(简称MQR),采用mirai的Android�??议实现的QQ机器人�?务,通过web控制机器人的�?��?�和�?置
- 测试解决方案或工具
alibaba/jvm-sandbox-repeater
A Java server-side recording and playback solution based on JVM-Sandbox, 录制/回放通用解决方案vivo/MoonBox
Moonbox(月光�?盒)是JVM-Sandbox生�?下的,基于jvm-sandbox-repeater�?新开�?�的,一款�?�?回放平�?�产�?。相较于jvm-sandbox-repeater,MoonboxåŠŸèƒ½æ›´åŠ ä¸°å¯Œï¿½?数�?��?��?�性更高,�?�时便于快速线上部署和使用alibaba/testable-mock
�?��?�?路写Mock,让�?�元测试更简�?�shulieTech/Takin
全链路压测平�?�,measure online environmental performance test for full-links, Especially for microservicesshulieTech/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版实现
Spring Cloud/Spring Boot的框架方案/脚手架YunaiV/ruoyi-vue-pro
一套全部开�?的�?业级的快速开�?�平�?�。基于 Spring Boot + MyBatis Plus + Vue & Element 实现的�?��?�管�?�系统 + 微信�?程�?,支�? RBAC 动�?�?��?�?数�?��?��?�?SaaS 多租户�?Activiti + Flowable 工作�?�?三方登录�?支付�?çŸä¿¡ï¿½?商城ç‰åŠŸèƒ½YunaiV/yudao-cloud
RuoYi-Vue 全新 Cloud 版本,优化�?构所有功能。基于 Spring Cloud Alibaba + MyBatis Plus + Vue & Element 实现的�?��?�管�?�系统 + 用户�?程�?,支�? RBAC 动�?�?��?�?多租户�?数�?��?��?�?工作�?�?三方登录�?支付�?çŸä¿¡ï¿½?商城ç‰åŠŸèƒ½zlt2000/microservices-platform
基于SpringBoot2.x�?SpringCloud和SpringCloudAlibaba并采用�?�?�端分离的�?业级微�?务多租户系统架构dromara/lamp-cloud
基于Jdk11 + SpringCloud + SpringBoot 的微�?务快速开�?�平�?�,其ä¸çš„�?��?置的SaaS功能尤其闪耀, 具备RBAC功能�?网关统一鉴�?��?Xss防跨站攻击�?自动代�?生�?�?多�?å˜å‚¨ç³»ç»Ÿï¿½?分布�?事务�?分布�?定时任务ç‰å¤šä¸ªæ¨¡ï¿½?�,支�?多业务系统并行开�?�, 支�?多�?务并行开�?�,�?�以作为�?�端�?务的开�?�脚手架zuihou/lamp-util
æ‰“é€ ä¸€å¥—å…¼é¡¾ SpringBoot å’Œ SpringCloud 项目的公共工具类
matevip/matecloud
一款基于Spring Cloud Alibaba的微�?务架构gavenwangcn/vole
SpringCloud 微�?务业务脚手架liuweijw/fw-cloud-framework
基于springcloud全家桶开�?�分布�?框架(支�?oauth2认�?授�?��?SSO登录�?统一下�?��?微信公众�?��?务�?Shardingdbc分库分表�?常�?�?务监控�?链路监控�?å¼‚æ¥æ—¥å¿—�?redis缓å˜ç‰åŠŸèƒ½ï¼‰ï¼Œå®žçŽ°åŸºäºŽVue全家桶ç‰ï¿½?�?�端分离项目工程liuht777/Taroco
整�?�Nacos�?Spring Cloud Alibaba,�??供了一系列starter组件, �?�时�??供�?务治�?��?�?务监控�?OAuth2�?��?认�?,支�?�?务�?级/熔æ–�?�?务�?��?mingyang66/spring-parent
数�?�库多数�?��?�?Redis多数�?��?�?日志组件�?全链路日志追踪�?埋点扩展点�?Netty�?微�?务�?开�?�基础框架支�?�?异常统一处�?��?返回值�?跨域�?API路由�?监控ç‰budwk/budwk
BudWk原�??NutzWk,基于国产框架 nutz �?� nutzboot 开�?�的开�?Web基础项目,集�?��?体系�?系统�?�数�?数�?�å—典�?站内消�?��?定时任务�?CMS�?å¾®ä¿¡ç‰æœ€å¸¸ç”¨åŠŸèƒ½ï¼Œï¿½?庞�?��?�?�?��?�俱到,使其具有上手容易�?开�?�便�?��?扩展�?�活ç‰ç‰¹æ€§ï¼Œç‰¹åˆ«é€‚�?��?�类大ä¸ï¿½?型定制化项目需求
yinjihuan/spring-cloud
《Spring Cloud微�?务-å…¨æ ˆæŠ€æœ¯ä¸Žæ¡ˆä¾‹è§£ï¿½?》和《Spring Cloud微�?务 入门 实战与进阶》�?套�?�?louyanfeng25/ddd-demo
《深入浅出DDD》讲解的演示项目,为了能够更好的�?�解Demoä¸çš„分层与逻辑处�?ï¿½ï¼Œæˆ‘å¼ºçƒˆå»ºè®®ä½ ï¿½?�?��?册�?�深入了解DDD
更多使用TTL的开�?项目 �?��?
👷 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
- rybalkinsd <yan.brikl at gmail dot com> @rybalkinsd
- David Dai <351450944 at qq dot com> @LNAmp
- Your name here :-)



