Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement FastThreadLocal mode of Netty #94

Open
oldratlee opened this issue Jun 24, 2018 · 9 comments
Open

implement FastThreadLocal mode of Netty #94

oldratlee opened this issue Jun 24, 2018 · 9 comments

Comments

@oldratlee
Copy link
Member

oldratlee commented Jun 24, 2018

  • Keep the interface unchanged
  • Provides a high-performance implementation of FastThreadLocal.

  • 使用接口不变
  • 提供FastThreadLocal的高性能实现。
@driventokill driventokill self-assigned this Jul 23, 2018
@xwshiustc
Copy link
Collaborator

xwshiustc commented Aug 7, 2018

考虑如下实现

在现有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,该类模拟InheritableThreadLocalTransmittableThreadLocal的部分行为,使其拥有

  1. 和InheritableThreadLocal类似的,在Thread构造方法调用init方法时返回parentValue的功能 实现和InheritableThreadLocal想雷同的逻辑
  2. 模仿Transmittable相同的逻辑 提供private static TtlFastThreadLocal<Map< TtlFastThreadLocal, ?>> holder 来实现父子线程的内容传递和还原

因为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

@oldratlee oldratlee changed the title integration FastThreadLocal mode of Netty implement FastThreadLocal mode of Netty Aug 7, 2018
@xwshiustc
Copy link
Collaborator

理解错误,上面论述是对netty本身使用ttl上下文的方案。 我们要讨论的是如何将netty中的高性能引入到ttl中,上面的方案作废!

@driventokill
Copy link
Member

可以考虑把 Ttl 存储接口分离出来,根据运行时环境检测选择具体的实现,有 FastThreadLocal 的环境使用 FastThreadLocal 实现,后续甚至可以考虑让用户自己实现自己的存储方案,通过 spi 的方式加载进来

@oldratlee
Copy link
Member Author

oldratlee commented Aug 7, 2018

可以考虑把 Ttl 存储接口分离出来

  • 这个分离根据 实现的复杂膨胀 和 实际的灵活性 来定。
  • 根据TTL的『概念』边界来 分离 出『子概念』,这个通过 需求及其设计现实 的感知 再定。

综上,是否做分离 先 提前决策。

@driventokill

@driventokill
Copy link
Member

driventokill commented Aug 7, 2018

在支持 FastThreadLocal 的环境下,每个 Ttl 创建一个 FastThreadLocal (这个就是我说的想抽出来做成一个存储接口),现在每个 Ttl 的存储其实是 InheritableThreadLocal 实现,所以每次都是使用 super.getsuper.set 来完成值的读取和设置,分别比较一下:

前提

假定每个 Ttl 有一个 FastThreadLocal :

private FastThreadLocal<T> fastThreadLocal = new FastThreadLocal<>();

读取

现有实现

public final T get() {
        T value = super.get();
        if (null != value) {
            addValue();
        }
        return value;
    }

FastThreadLocal

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();
        }
    }

FastThreadLocal

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();
    }

FastThreadLocal

public final void remove() {
        removeValue();
        //super.remove();
        fastThreadLocal.remove();
    }

@xwshiustc
Copy link
Collaborator

目前Ttl jar在xbootclasspath中,而 FastThreadLocal是第三方jar,感觉上netty不应也融入xbootclasspath,所以简单地在TransmittableThreadLocal中引入 FastThreadLocal 不知道是否可以。

@driventokill
Copy link
Member

简单地在TransmittableThreadLocal中引入 FastThreadLocal 不知道是否可以

实现的时候并不会这么简单,需要对环境检测一下,只是在运行时有 FastThreadLocal 支持的情况下才会创建。我上面写法只是为了表达更清晰一点

@xwshiustc

@xwshiustc
Copy link
Collaborator

明白 理解了。

@driventokill driventokill added this to the 2.6.2 milestone Aug 7, 2018
driventokill added a commit that referenced this issue Aug 7, 2018
1. Support FastThreadLocal mode when run with netty by config
   -Dttl.fastthreadlocal.enable=true, default is false
2. Caution: when FastThreadLocal mode is enabled,
   TransmittableThreadLocal can NEVER be inheritable.
3. Disable the tests which depends on the ability of InheritableThreadLocal
   when FastThreadLocal is enabled.
driventokill added a commit that referenced this issue Aug 7, 2018
1. Support FastThreadLocal mode when run with netty by config
   -Dttl.fastthreadlocal.enable=true, default is false
2. Caution: when FastThreadLocal mode is enabled,
   TransmittableThreadLocal can NEVER be inheritable.
3. Disable the tests which depends on the ability of InheritableThreadLocal
   when FastThreadLocal is enabled.
driventokill added a commit that referenced this issue Aug 7, 2018
1. Support FastThreadLocal mode when run with netty by config
   -Dttl.fastthreadlocal.enable=true, default is false
2. Caution: when FastThreadLocal mode is enabled,
   TransmittableThreadLocal can NEVER be inheritable.
3. Disable the tests which depends on the ability of InheritableThreadLocal
   when FastThreadLocal is enabled.
driventokill added a commit that referenced this issue Aug 8, 2018
1. Support FastThreadLocal mode when run with netty by config
   -Dttl.fastthreadlocal.enable=true, default is false
2. Caution: when FastThreadLocal mode is enabled,
   TransmittableThreadLocal can NEVER be inheritable.
3. Disable the tests which depends on the ability of InheritableThreadLocal
   when FastThreadLocal is enabled.
@oldratlee oldratlee removed this from the 2.7.0 milestone Sep 18, 2018
@IgorKey
Copy link

IgorKey commented Oct 27, 2019

@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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants