Open oldratlee opened 6 years ago
考虑如下实现
在现有transmittable-thread-local-x.x.x.jar
的基础上新开发第二个可选jar:netty-ttl-plugin.jar
(这次新开发),并且netty-ttl-plugin.jar
依赖transmittable-thread-local-X.X.X.jar
(ttl已有)和netty-all-X.X.X.jar
(netty开源).
注意到io.netty.util.concurrent.FastThreadLocal
继承自Object
,和java.lang.ThreadLocal
没有任何继承关系,考虑在netty-ttl-plugin.jar
中新建一个io.netty.util.concurrent.FastThreadLocal
的子类TtlFastThreadLocal
,该类模拟InheritableThreadLocal
和TransmittableThreadLocal
的部分行为,使其拥有
因为FastThreadLocal需要配合io.netty.util.concurrent.FastThreadLocalThread
才能发挥其fast的威力,观察FastThreadLocalThread
它直接继承自Thread
,并且内部拥有一个private InternalThreadLocalMap threadLocalMap
来保存FastThreadLocal
的键值对,我们可以继续再写一个子类继承TtlFastThreadLocalThread
继承FastThreadLocalThread
,然后添加成员变量private InternalThreadLocalMap ttlThreadLocalMap
来保存新的TtlFastThreadLocal
键值对,同时改变其所有的构造方法,所有构造方法加入init
方法,init
方法大体逻辑如下
public void init(){
Thread parent = currentThread();
if (parent.ttlThreadLocalMap != null){
this.ttlThreadLocalMap =ThreadLocal.createInternalThreadLocalMap(parent.ttlThreadLocalMap);
}
... ... //可能还有其他逻辑
}
实现TtlFastThreadLocal内具备InheritableThreadLocal相似功能。
TtlFastThreadLocalThread 设置为final类不允许被继承,同时TtlFastThreadLocalThread 代理其run方法使其所有run方法拥有类似ttlRunable中的如下代码块大概主体逻辑
public TtlFastThreadLocalThread extends FastThreadLocalThread{
FastThreadLocalThread fastThreadLocalThread;
private InternalThreadLocalMap ttlThreadLocalMap;
public void run(){
Object backupFastTtl = replay(capturedFastTtl);
try {
fastThreadLocalThread.run();
} finally {
restoreFastTtl(backupFastTtl);
}
}
......
}
从上一线程复制引用,传递给下一个线程 ,并在使用后还原。以上为主体逻辑保持,使用方式:
FastThreadLocal t = new TtlFastThreadLocal();
t.put("1");
FastThreadLocalThread ftlt = new TtlFastThreadLocalThread(原来的FastThreadLocalThread);---标记1
因为netty的限制,想用FastThreadLocal的fast特性则代码中一定要使用FastThreadLocalThread配合他,两者在fast情况下必然成对出现,所以,我们只要考虑FastThreadLocalThread的改造即可,不用考虑普通的Runnable Callable 怎么实现!
在fastThreadLocal的slow模式下((Thread.currentThread() instanceof FastThreadLocalThread) ==false) 其内部靠的是普通的ThreadLocal实现, 所以我们只要在TtlFastThreadLocal内部slow调用实现全部从ThreadLoad替换为TransmittableThreadLocal即可。 【目前直觉感觉可行】
transmittable-thread-local-x.x.x.jar的TtlAgent只加强FastThreadLocalThread即可,用雷同TtlRunnable.get(Runnable runnable)的方式在 TtlFastThreadLocalThread.get(FastThreadLocalThread)的方式加强实现FastThreadLocalThread的代理。故上面“---标记1”处的方法也可以改为该静态方法
transmittable-thread-local-x.x.x.jar的TtlAgent的字节码加强的治入点仍然和原来的实现相似比如java.util.concurrent.ThreadPoolExecutor的一些列方法,但是假如逻辑判断,如果外部传入线程Runnable s实现为FastThreadLocalThread的子类的情况下,使用TtlFastThreadLocalThread.get(FastThreadLocalThread)的加强方式加强线程,其他情况仍然调用字节码加强TtlRunnable get(Runnable runnable, boolean releaseTtlValueReferenceAfterRun, boolean idempotent)
当业务程序只需要ttl不需要ttlFastThreadLocal的时候,只使用transmittable-thread-local-x.x.x.jar, 如果想用FastThreadLocal的自动传递,可依赖netty-ttl-plugin.jar
理解错误,上面论述是对netty本身使用ttl上下文的方案。 我们要讨论的是如何将netty中的高性能引入到ttl中,上面的方案作废!
可以考虑把 Ttl 存储接口分离出来,根据运行时环境检测选择具体的实现,有 FastThreadLocal 的环境使用 FastThreadLocal 实现,后续甚至可以考虑让用户自己实现自己的存储方案,通过 spi 的方式加载进来
可以考虑把 Ttl 存储接口分离出来
TTL
的『概念』边界来 分离 出『子概念』,这个通过 需求及其设计现实 的感知 再定。综上,是否做分离 先 不 提前决策。
@driventokill
在支持 FastThreadLocal 的环境下,每个 Ttl 创建一个 FastThreadLocal (这个就是我说的想抽出来做成一个存储接口),现在每个 Ttl 的存储其实是 InheritableThreadLocal 实现,所以每次都是使用 super.get
和 super.set
来完成值的读取和设置,分别比较一下:
假定每个 Ttl 有一个 FastThreadLocal :
private FastThreadLocal<T> fastThreadLocal = new FastThreadLocal<>();
public final T get() {
T value = super.get();
if (null != value) {
addValue();
}
return value;
}
public final T get() {
//T value = super.get();
T value = fastThreadLocal.get();
if (null != value) {
addValue();
}
return value;
}
public final void set(T value) {
super.set(value);
if (null == value) { // may set null to remove value
removeValue();
} else {
addValue();
}
}
public final void set(T value) {
//super.set(value);
fastThreadLocal.set(value);
if (null == value) { // may set null to remove value
removeValue();
} else {
addValue();
}
}
public final void remove() {
removeValue();
super.remove();
}
public final void remove() {
removeValue();
//super.remove();
fastThreadLocal.remove();
}
目前Ttl jar在xbootclasspath中,而 FastThreadLocal是第三方jar,感觉上netty不应也融入xbootclasspath,所以简单地在TransmittableThreadLocal中引入 FastThreadLocal 不知道是否可以。
简单地在TransmittableThreadLocal中引入 FastThreadLocal 不知道是否可以
实现的时候并不会这么简单,需要对环境检测一下,只是在运行时有 FastThreadLocal 支持的情况下才会创建。我上面写法只是为了表达更清晰一点
@xwshiustc
明白 理解了。
@driventokill @oldratlee guys, could you please give the status of this issue? I tried this on netty, ofc it didn't work. Are there any workarounds for use this brilliant lib with netty fastThreads?