TTL v3 project management
oldratlee opened this issue · comments
关于TransmittableThreadLocal(TTL)
v3
🚧
TransmittableThreadLocal(TTL)
v3 在开发中(在master
分支),还没有发布。
新功能推荐都在v3
中提供,原因:
TTL
域的核心问题(包含了可扩展的能力、不包含扩展的实现)在v2
解决了,并且稳定;TTL
核心功能,v2
已经是开放的- 如果你觉得有必要或是喜欢想试一下,
可以用自己的实现来替代最核心TransmittableThreadLocal
类实现
- 如果你觉得有必要或是喜欢想试一下,
- 这让维持
v2
聚焦v3
升级 成为可能。
- 避免
v2
老版本的 并行大维护工作 与 保持兼容性的历史包袱(如不优或过度的设计、对低版本Java
的支持),从而在v3
聚焦输出有价值的工作。v3
作为在大版本升级,可以是不兼容升级- 当然会提供
TTL v2
的兼容包(即ttl2-compatible 3.x
模块),以简化用户的升级过程
- 通过
v3
有价值的新功能可以引导大家从v2
升级、试用/使用、优化v3
。
已有的相关讨论:
- #173 (comment)
TTL v3.x
重点会是
- 对常用的周边框架的使用做一等公民的体验优化支持。
- 如,开发框架王者
Spring
/Spring Boot
的集成- PS:
JDK
标准库涉及类的集成,v2
已经做了TTL Agent
的扩展开放,方便三方自己做类增强的集成。
- 执行组件很多,这些涉及的类增强,在
TTL
库中不可能都做支持- PS:用于框架集成的
API
(核心是Transmitter
),v2
已经开放了- ……
TTL
核心功能,v2
已经是开放的,即
- 没有什么功能 只能在
TTL
库中才能实现。- 或说成,需要的功能 可以在
TTL
库外部来扩展实现。- 在
TTL
项目中,扩大集成范围,可以优化大家平时常用场景开箱即用的使用体验。- 其实,不少方便使用的
TTL
集成/增强,各个大厂是会有实现的,但并没开源出来;这些使用便利的地方值得进一步解决得更好。- #405 (comment)
TTL v3
会提供
- 无
shade
的API
依赖- 分离用户
API
与Agent
成2个依赖- 也可以提供
spring-boot loader + fatjar
模式依赖v3
作为大版本升级,可以做不兼容的修改,清理掉不好的设计与实现;当然会提供TTL v2
的兼容包。v3
会提供Kotlin
语言的一等公民支持。- #377 (comment)
到了现在,因为库的兼容性,也不能删除掉这个扩展点了 😢- #412 (comment)
- 如果你觉得
TTL
带的实现 不优 或是 可以结合你自己的业务场景来优化,
TTL v2.14.0
提供了 可以自己实现ThreadLocal
注册的入口:
即不用TransmittableThreadLocal
实现类,改用你自己的实现类。
下面是v3
的工作项列表及其进展。
TTL core
API 不兼容升级
❗️ 不兼容
- ✨
TransmittableThreadLocal#copy
方法名改成transmiteeValue
- 虽然多数情况下,传递的是一个复杂的对象,习惯上会先想到的是如何做拷贝,如深拷贝、浅拷贝;这个方法
copy
是容易想到和理解这个过程与行为了。 😂- 这是也是为什么在
TTL v2
中,这个方法被命名成了copy
的原因。
- 这是也是为什么在
- 但是『传递』是更严谨且合理的,因为并不一定有『拷贝』行为(比如简单的赋值传递)。
transmiteeValue
命名也与JDK
的InheritableThreadLocal.childValue()
方法名有了一致性。
- 虽然多数情况下,传递的是一个复杂的对象,习惯上会先想到的是如何做拷贝,如深拷贝、浅拷贝;这个方法
- ✨ 去除
TransmittableThreadLocal
的before/after execute
方法TransmittableThreadLocal
类是TTL
的用户API
,要尽量简化,包含的是核心功能(非外围/可附加的功能)- 通过
Transmitter
支持before/after execute
回调的注册Transmitter
是TTL
的开发者API
;开发者角色可以关注生命周期这样完备也复杂的问题
- 更多讨论
- 内部类
TTL Transmitter
上提到根包下,成为子包transmitter
- 而不是内部类,核心概念不够一等公民
- 也导致了核心的
TransmittableThreadLocal
类文件越写越长…
- ✨ #168
TTL Transmitter
的CRR
方法 返回具体类型,而不是Object
- 删除(隐藏的)接口(本来就是不开放的接口,删除了实现更简单)
- 删除(隐藏的)
DisableInheritableThreadFactory
接口 - 删除(隐藏的)
DisableInheritableForkJoinWorkerThreadFactory
- 删除(隐藏的)
- 减少工具方法个数简化
API
- ✨ rename package
threadpool
toexecutor
(72c6b69) - 删除
TtlUnwrap
类,该类的方法合并到TtlWrappers
类 (5b68280)
在v2
中这些工具方法放在TtlUnwrap
类中是为了支持Java 6
;v3
支持Java 8+
,不再需要这么做了。 - 删除
TtlForkJoinPoolHelper
类,该类的方法合并到TtlExecutors
类 (5b68280)
原因同上 - 删除
v2
中@Deprecated
的类与方法: (5b68280)com.alibaba.ttl.TtlEnhanced
com.alibaba.ttl.TtlWrappers#wrap(...)
Transmittance/CRR
分离成独立包(成为一个小框架)
就像 https://github.com/reactive-streams/reactive-streams-jvm
这种 核心小框架 抽象后,相信意义很大:
CRR
概念/模式有普遍性,分离独立 可以对核心问题给出高水准与高强度的设计与实现。- 即使不被业界其它项目使用,只是
TTL
自身在使用,也可以提升TTL
自身的设计与实现,如模块化/扩展性/概念分离。
- 可以注册不同的
ThreadLocal
(如Netty
的FastThreadLocal
),扩展性提升/三方平等的设计。Transmittance
生命周期回调(callback
)的提供 是 清晰、规范的。- 设计的优化 可以带来
TTL
自身实现的可靠性提升。
- 显化核心概念:
transmitter
、transmittee
、CRR
- 这个小框架要 独立/自包含,不能依赖上层(即
TTL
)。TransmittableThreadLocal
也只是CRR
的一个普通使用方TTL Transmitter
类(TTL
的使用方)仍以static
方法的方式暴露TTL CRR
操作- 上下文异常如何具体场景化?
-
CRR
作为TTL
开发扩展的下层API
,与TTL
用户API
分离开。- 放在
com.alibaba.crr
包下 - 注意:不位于
com.alibaba.ttl3
包下,在包名上也体现出了CRR
与TTL
的独立性。 -
TransmittableThreadLocal
创建、持有并注册TtlTransmittee
(静态实例)。
TTL Transmitter
实例化TtlTransmittee
并持有。
- 放在
- 🆕✨ 通过
Transmitter
支持before/after execute
回调及其注册
可以支持TTL v2
的已有功能/v3
中去除的功能(TransmittableThreadLocal
的before/after execute
方法) -
Transmitter
支持before/after execute
回调方法的调用是一致性的(4ba3dd6)- 一致性是指:对于注册的
CrrTransmitCallback
实例:- 收到回调
beforeX
就一定要收到afterX
- 收到回调
xReplay
就一定要收到xRestore
- 收到回调
- 这样一致的回调 保证了,即使在回调中包含资源管理的逻辑也不会带来资源泄漏的问题。
- 一致性是指:对于注册的
v2.14.0
支持了ThreadLocal
的注册,三方平等支持(如FastThreadLocal
)
https://github.com/alibaba/transmittable-thread-local/releases/tag/v2.14.0
TTL Agent
✨🆕 TTL Agent
模块化
- #260
- 分离
Agent Jar
与API Jar
- 这样
API
包大小很小,用户运行时依赖不excludeTTL
包而冗余了也成本小 - 方便
Agent
包支持不同的打包格式,不同场景使用友好
- 分离
- 提供没有
shade
依赖的TTL Agent
包- 方便方便使用方
repackage
/shade
依赖 - 打包
TTL Agent
到自己的Agent
包中,并且共享一份shade
的依赖(如字节码库) - 具体设计、实现与使用方式,可以参照
byte-buddy
- 方便方便使用方
- 提供常用的
Agent
打包格式
TTL Agent
的扩展机制
可以加载应用中的类增强的逻辑实现,但不需要三方提供Java Agent
实现;
从而简化三方提供Agent
的类增强逻能力。
TTL
的集成往往涉及API
与Agent
两者的支持。
- 🆕 提供
Agent
的扩展机制
✨ TTL Agent
支持运行时加载生效
- 🆕 #169
TTL Agent
支持运行时加载生效 - 引入
ConcurrentWeakMap
/ConcurrentWeakHashMap
(ade56ea)- 在
Spring
中有ConcurrentWeakHashMap
实现 - 注意:提供工厂方法以返回接口的实现的实例,实现类隐藏掉;这样方便后面切换(更好的)实现
- 目前还没有引入
ConcurrentWeakMap
,实现内部使用,不需要复杂化
- 在
- 通过
ConcurrentWeakMap
存储类实例与capture
的关联 替代 在已有的类上新增capture
字段- 这样的方案,不会给要增强的类新增字段(即不改变的类结构),从而
Agent
可以在运行时增强已有的类; - 但会增加
GC
负担,考虑只在运行时加载TTL Agent
时使用这个方案。
- 这样的方案,不会给要增强的类新增字段(即不改变的类结构),从而
- 整理
Agent
开发相关的文档到
#169
配置体验优化
- 🆕 使用
-D properties
来配置TTL Agent
,而不是Agent
参数。- 更友好方便,
Agent
参数写起来读起来繁琐易错。
- 更友好方便,
Agent
字节码实现
- 改用
byte-buddy
实现
测试
-
v2
单元测试迁移到v3
-
TTL core
模块 -
TTL Agent
模块
-
注意:原则上,v2
的测试代码一行不能改,以确保尽量发现兼容包的v2
功能break。
文档
- 更新
markdown
文档中的文件链接,因为模块移动了目录 -
v3
文档中去除v2
的版本新功能说明,v3
中v2
功能都一开始就有的 - 业务场景中,说明上典型的业务上下文,如登录/授权的用户ID、平台的租户ID
ttl2-compatible
的实现成代理到TTL3
- 需要 在
v2
的相关方法(如check
)中,兼容逻辑
添加通过v3
实现类来判断的兼容逻辑 - 添加
@Deprecated
及其说明- 说明包含:推荐使用
v3
、v3
的用法、v3
与v2
不兼容的内容
- 说明包含:推荐使用
生态集成支持
往往涉及API
与Agent
两者的支持
🆕✨ Kotlin
支持
🆕✨ Spring/SpringBoot
集成
- 执行器
wrapper
支持Spring
,集成Spring Async Executors
#173- 简化使用,在效果上像
Agent
但配置更简单 - 感觉『Bean注入时拦截做包装』更好,不是『Bean生成时拦截』
-
API
支持。参考项目Dreamroute/ttl-spring-boot-starter
- 提供
Spring/SpringBoot
注解,如@EnableTtlExecutor
,@SkipTttlWrapper
- 提供
-
Agent
支持
- 简化使用,在效果上像
- 提供
session cache
的Spring
支持
Misc
待细化展开
优化(如性能)
-
TtlAttachments
没有使用时不创建,比如在TtlRunnable
中的使用 - 异常捕捉处理:不要捕捉
Throwable
,只捕捉NonFatal Exception
(8eb51d4)- 实现参考:
- source code: https://github.com/scala/scala/blob/v2.13.9/src/library/scala/util/control/NonFatal.scala#L35-L43
- scala doc:
scala.util.control
- performance optimization, use
expected size
to initializehash map
instead ofcapacity
(8590e25) - fix wrong
equals
/hashCode
implementations of TTL wrappers (4f18607) - 🆕 add
ttl-bom
(d573053)
v3有没有发布的时间点?
v3有没有发布的时间点?
还没有定 😄 @mingyang66
一方面,重构/新增的内容有些多,期望想得清楚些。
另一方面,有v2
可用,倒不紧急。
谢谢关注 💕
大家如果有实际/目标的场景需求 可以提,以调整实现优先级和发布节奏。
v3有没有发布的时间点?
还没有定 😄 @mingyang66
一方面,重构/新增的内容有些多,期望想得清楚些。 另一方面,有
v2
可用,倒不紧急。谢谢关注 💕
大家如果有实际/目标的场景需求 可以提,以调整实现优先级和发布节奏。
OK,最近一直在关注TTL的更新
集成SkyWalking这部分,请问打算怎么迭代呢,是否会成为skywalking的自定义插件模式支持~
集成SkyWalking这部分,请问打算怎么迭代呢,是否会成为skywalking的自定义插件模式支持~
- 集成的这部分内容,可以做的要做的比较多。 😂
- 对于使用多、问题明显的,优先级高。 💕
- PS: 整体
TTL v3
没有定发布节奏,原因见上面的评论内容
明白,感谢回复;最近在使用skywalking的多线程插件时遇到了些问题,发现如果测试应用使用了自定义加载器会导致切入异常,所以看到了TTL,有想用TTL替换skywalking中的多线程插件的想法
如果测试应用使用了自定义加载器会导致切入异常,所以看到了TTL
嗯嗯 ❤️ @haoyongdong
这个所涉及的「支持运行时加载TTL Agent #169」(即使只用在测试场景),
个人觉得优先级高。💪
- 实现思路 已经想得差不多了
- 反馈Issue也比较多
参见上面内容 及其 相关已有Issue的讨论
SkyWalking目前在SpringCloudGateway中的问题较多,如果TTL能成为SW的上下文进程内容器就好了
如果测试应用使用了自定义加载器会导致切入异常,所以看到了TTL
嗯嗯 ❤️ @haoyongdong
这个所涉及的「支持运行时加载TTL Agent」(即使只用在测试场景), 个人觉得优先级高。💪
- 实现思路 已经想得差不多了
- 反馈Issue也比较多
参见上面内容 及其 相关已有Issue的讨论
大佬,能简单说下实现的的思路吗?我们自己内部也在尝试
能简单说下实现的的思路吗?我们自己内部也在尝试
@cxntsh 实现的的思路,在上面 issue 的正文中,有一些说明:
通过
ConcurrentWeakMap
存储类实例与capture
的关联 替代 在已有的类上新增capture
字段
- 这样的方案,不会给要增强的类新增字段(即不改变的类结构),从而
Agent
可以在运行时增强已有的类;- 但会增加
GC
负担,考虑只在运行时加载TTL Agent
时使用这个方案。
hi @oldratlee !我正在尝试基于 master 实现如下功能:
通过ConcurrentWeakMap存储类实例与capture的关联 替代 在已有的类上新增capture字段
- 这样的方案,不会给要增强的类新增字段(即不改变的类结构),从而Agent可以在运行时增强已有的类;
- 但会增加GC负担,考虑只在运行时加载TTL Agent时使用这个方案。
但是当我在执行测试的时候发现代码不能正确的运行,请问 master 分支代码当前是处于不可正常运行状态吗?
如果测试应用使用了自定义加载器会导致切入异常,所以看到了TTL
嗯嗯 ❤️ @haoyongdong
这个所涉及的「支持运行时加载TTL Agent」(即使只用在测试场景), 个人觉得优先级高。💪
- 实现思路 已经想得差不多了
- 反馈Issue也比较多
参见上面内容 及其 相关已有Issue的讨论
大佬,请问这部分的实现现在有代码示例了吗?
我想通过使用ttl代替skywalking中的threadlocal作为上下文传递,
然后按照 #226 中所说先加载ttl agent,再加载skywalking agent,
尝试实现无侵入的全链路传递链路数据
@oldratlee 大佬,估计什么时候能完成kotlin协程的支持。现在kotin协程在后端用的越来越多啦!感谢大佬!