Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
zhangjian1949
microservices-platform
提交
fc469f04
microservices-platform
项目概览
zhangjian1949
/
microservices-platform
与 Fork 源项目一致
Fork自
zlt2000 / microservices-platform
通知
6
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
microservices-platform
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
fc469f04
编写于
8月 17, 2019
作者:
zlt2000
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
优化租户和MDC信息的父子线程传递方式
上级
51ca3b6a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
242 addition
and
76 deletion
+242
-76
pom.xml
pom.xml
+6
-0
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/utils/CustomThreadPoolTaskExecutor.java
...om/central/common/utils/CustomThreadPoolTaskExecutor.java
+15
-75
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/utils/TenantContextHolder.java
...in/java/com/central/common/utils/TenantContextHolder.java
+6
-1
zlt-commons/zlt-log-spring-boot-starter/pom.xml
zlt-commons/zlt-log-spring-boot-starter/pom.xml
+5
-0
zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/config/TtlMDCAdapterInitializer.java
...java/com/central/log/config/TtlMDCAdapterInitializer.java
+19
-0
zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java
...g-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java
+188
-0
zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories
...boot-starter/src/main/resources/META-INF/spring.factories
+3
-0
未找到文件。
pom.xml
浏览文件 @
fc469f04
...
@@ -39,6 +39,7 @@
...
@@ -39,6 +39,7 @@
<txlcn.version>
5.0.2.RELEASE
</txlcn.version>
<txlcn.version>
5.0.2.RELEASE
</txlcn.version>
<fastdfs-client.version>
1.26.5
</fastdfs-client.version>
<fastdfs-client.version>
1.26.5
</fastdfs-client.version>
<userAgent.version>
1.21
</userAgent.version>
<userAgent.version>
1.21
</userAgent.version>
<transmittable.version>
2.11.0
</transmittable.version>
<platform-bom>
Cairo-SR3
</platform-bom>
<platform-bom>
Cairo-SR3
</platform-bom>
<spring-cloud-alibaba-dependencies.version>
2.0.0.RELEASE
</spring-cloud-alibaba-dependencies.version>
<spring-cloud-alibaba-dependencies.version>
2.0.0.RELEASE
</spring-cloud-alibaba-dependencies.version>
<spring-boot-dependencies.version>
2.0.9.RELEASE
</spring-boot-dependencies.version>
<spring-boot-dependencies.version>
2.0.9.RELEASE
</spring-boot-dependencies.version>
...
@@ -297,6 +298,11 @@
...
@@ -297,6 +298,11 @@
<artifactId>
UserAgentUtils
</artifactId>
<artifactId>
UserAgentUtils
</artifactId>
<version>
${userAgent.version}
</version>
<version>
${userAgent.version}
</version>
</dependency>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
transmittable-thread-local
</artifactId>
<version>
${transmittable.version}
</version>
</dependency>
<dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<groupId>
org.springframework.boot
</groupId>
...
...
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/utils/CustomThreadPoolTaskExecutor.java
浏览文件 @
fc469f04
package
com.central.common.utils
;
package
com.central.common.utils
;
import
c
n.hutool.core.util.StrUtil
;
import
c
om.alibaba.ttl.TtlCallable
;
import
org.slf4j.MDC
;
import
com.alibaba.ttl.TtlRunnable
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
;
import
org.springframework.util.concurrent.ListenableFuture
;
import
org.springframework.util.concurrent.ListenableFuture
;
import
java.util.Map
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
/**
/**
* 这是{@link ThreadPoolTaskExecutor}的一个简单替换,可
以在每个任务之前设置子线程的租户和MDC数据
* 这是{@link ThreadPoolTaskExecutor}的一个简单替换,可
搭配TransmittableThreadLocal实现父子线程之间的数据传递
*
*
* @author zlt
* @author zlt
* @date 2019/8/14
* @date 2019/8/14
*/
*/
public
class
CustomThreadPoolTaskExecutor
extends
ThreadPoolTaskExecutor
{
public
class
CustomThreadPoolTaskExecutor
extends
ThreadPoolTaskExecutor
{
/**
private
static
final
long
serialVersionUID
=
-
5887035957049288777L
;
* 把父线程的租户和MDC内容赋值给子线程
* @param runnable
*/
@Override
@Override
public
void
execute
(
Runnable
runnable
)
{
public
void
execute
(
Runnable
runnable
)
{
String
tenantId
=
TenantContextHolder
.
getTenant
();
Runnable
ttlRunnable
=
TtlRunnable
.
get
(
runnable
);
Map
<
String
,
String
>
mdcContext
=
MDC
.
getCopyOfContextMap
();
super
.
execute
(
ttlRunnable
);
super
.
execute
(()
->
run
(
runnable
,
tenantId
,
mdcContext
));
}
}
@Override
@Override
public
<
T
>
Future
<
T
>
submit
(
Callable
<
T
>
task
)
{
public
<
T
>
Future
<
T
>
submit
(
Callable
<
T
>
task
)
{
String
tenantId
=
TenantContextHolder
.
getTenant
();
Callable
ttlCallable
=
TtlCallable
.
get
(
task
);
Map
<
String
,
String
>
mdcContext
=
MDC
.
getCopyOfContextMap
();
return
super
.
submit
(
ttlCallable
);
return
super
.
submit
(()
->
call
(
task
,
tenantId
,
mdcContext
));
}
}
@Override
@Override
public
Future
<?>
submit
(
Runnable
task
)
{
public
Future
<?>
submit
(
Runnable
task
)
{
String
tenantId
=
TenantContextHolder
.
getTenant
();
Runnable
ttlRunnable
=
TtlRunnable
.
get
(
task
);
Map
<
String
,
String
>
mdcContext
=
MDC
.
getCopyOfContextMap
();
return
super
.
submit
(
ttlRunnable
);
return
super
.
submit
(()
->
run
(
task
,
tenantId
,
mdcContext
));
}
}
@Override
@Override
public
ListenableFuture
<?>
submitListenable
(
Runnable
task
)
{
public
ListenableFuture
<?>
submitListenable
(
Runnable
task
)
{
String
tenantId
=
TenantContextHolder
.
getTenant
();
Runnable
ttlRunnable
=
TtlRunnable
.
get
(
task
);
Map
<
String
,
String
>
mdcContext
=
MDC
.
getCopyOfContextMap
();
return
super
.
submitListenable
(
ttlRunnable
);
return
super
.
submitListenable
(()
->
run
(
task
,
tenantId
,
mdcContext
));
}
}
@Override
@Override
public
<
T
>
ListenableFuture
<
T
>
submitListenable
(
Callable
<
T
>
task
)
{
public
<
T
>
ListenableFuture
<
T
>
submitListenable
(
Callable
<
T
>
task
)
{
String
tenantId
=
TenantContextHolder
.
getTenant
();
Callable
ttlCallable
=
TtlCallable
.
get
(
task
);
Map
<
String
,
String
>
mdcContext
=
MDC
.
getCopyOfContextMap
();
return
super
.
submitListenable
(
ttlCallable
);
return
super
.
submitListenable
(()
->
call
(
task
,
tenantId
,
mdcContext
));
}
/**
* 子线程委托的执行方法
* @param runnable {@link Runnable}
* @param tenantId 租户id
* @param mdcContext 父线程MDC内容
*/
private
void
run
(
Runnable
runnable
,
String
tenantId
,
Map
<
String
,
String
>
mdcContext
)
{
// 将父线程的租户id传给子线程
if
(
StrUtil
.
isNotEmpty
(
tenantId
))
{
TenantContextHolder
.
setTenant
(
tenantId
);
}
// 将父线程的MDC内容传给子线程
if
(
mdcContext
!=
null
)
{
MDC
.
setContextMap
(
mdcContext
);
}
try
{
// 执行异步操作
runnable
.
run
();
}
finally
{
// 清空租户内容
TenantContextHolder
.
clear
();
// 清空MDC内容
MDC
.
clear
();
}
}
/**
* 子线程委托的执行方法
* @param task {@link Callable}
* @param tenantId 租户id
* @param mdcContext 父线程MDC内容
*/
private
<
T
>
T
call
(
Callable
<
T
>
task
,
String
tenantId
,
Map
<
String
,
String
>
mdcContext
)
throws
Exception
{
// 将父线程的租户id传给子线程
if
(
StrUtil
.
isNotEmpty
(
tenantId
))
{
TenantContextHolder
.
setTenant
(
tenantId
);
}
// 将父线程的MDC内容传给子线程
if
(
mdcContext
!=
null
)
{
MDC
.
setContextMap
(
mdcContext
);
}
try
{
// 执行异步操作
return
task
.
call
();
}
finally
{
// 清空租户内容
TenantContextHolder
.
clear
();
// 清空MDC内容
MDC
.
clear
();
}
}
}
}
}
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/utils/TenantContextHolder.java
浏览文件 @
fc469f04
package
com.central.common.utils
;
package
com.central.common.utils
;
import
com.alibaba.ttl.TransmittableThreadLocal
;
/**
/**
* 租户holder
* 租户holder
*
*
...
@@ -7,7 +9,10 @@ package com.central.common.utils;
...
@@ -7,7 +9,10 @@ package com.central.common.utils;
* @date 2019/8/5
* @date 2019/8/5
*/
*/
public
class
TenantContextHolder
{
public
class
TenantContextHolder
{
private
static
final
ThreadLocal
<
String
>
CONTEXT
=
new
ThreadLocal
<>();
/**
* 支持父子线程之间的数据传递
*/
private
static
final
ThreadLocal
<
String
>
CONTEXT
=
new
TransmittableThreadLocal
<>();
public
static
void
setTenant
(
String
tenant
)
{
public
static
void
setTenant
(
String
tenant
)
{
CONTEXT
.
set
(
tenant
);
CONTEXT
.
set
(
tenant
);
...
...
zlt-commons/zlt-log-spring-boot-starter/pom.xml
浏览文件 @
fc469f04
...
@@ -26,5 +26,10 @@
...
@@ -26,5 +26,10 @@
<groupId>
org.springframework.cloud
</groupId>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-context
</artifactId>
<artifactId>
spring-cloud-context
</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
transmittable-thread-local
</artifactId>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/config/TtlMDCAdapterInitializer.java
0 → 100644
浏览文件 @
fc469f04
package
com.central.log.config
;
import
org.slf4j.TtlMDCAdapter
;
import
org.springframework.context.ApplicationContextInitializer
;
import
org.springframework.context.ConfigurableApplicationContext
;
/**
* 初始化TtlMDCAdapter实例,并替换MDC中的adapter对象
*
* @author zlt
* @date 2019/8/17
*/
public
class
TtlMDCAdapterInitializer
implements
ApplicationContextInitializer
<
ConfigurableApplicationContext
>
{
@Override
public
void
initialize
(
ConfigurableApplicationContext
applicationContext
)
{
//加载TtlMDCAdapter实例
TtlMDCAdapter
.
getInstance
();
}
}
\ No newline at end of file
zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java
0 → 100644
浏览文件 @
fc469f04
package
org.slf4j
;
import
ch.qos.logback.classic.util.LogbackMDCAdapter
;
import
com.alibaba.ttl.TransmittableThreadLocal
;
import
org.slf4j.spi.MDCAdapter
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
/**
* 重构{@link LogbackMDCAdapter}类,搭配TransmittableThreadLocal实现父子线程之间的数据传递
*
* @author zlt
* @date 2019/8/17
*/
public
class
TtlMDCAdapter
implements
MDCAdapter
{
private
final
ThreadLocal
<
Map
<
String
,
String
>>
copyOnInheritThreadLocal
=
new
TransmittableThreadLocal
<>();
private
static
final
int
WRITE_OPERATION
=
1
;
private
static
final
int
MAP_COPY_OPERATION
=
2
;
private
static
TtlMDCAdapter
mtcMDCAdapter
;
/**
* keeps track of the last operation performed
*/
private
final
ThreadLocal
<
Integer
>
lastOperation
=
new
ThreadLocal
<>();
static
{
mtcMDCAdapter
=
new
TtlMDCAdapter
();
MDC
.
mdcAdapter
=
mtcMDCAdapter
;
}
public
static
MDCAdapter
getInstance
()
{
return
mtcMDCAdapter
;
}
private
Integer
getAndSetLastOperation
(
int
op
)
{
Integer
lastOp
=
lastOperation
.
get
();
lastOperation
.
set
(
op
);
return
lastOp
;
}
private
static
boolean
wasLastOpReadOrNull
(
Integer
lastOp
)
{
return
lastOp
==
null
||
lastOp
==
MAP_COPY_OPERATION
;
}
private
Map
<
String
,
String
>
duplicateAndInsertNewMap
(
Map
<
String
,
String
>
oldMap
)
{
Map
<
String
,
String
>
newMap
=
Collections
.
synchronizedMap
(
new
HashMap
<>());
if
(
oldMap
!=
null
)
{
// we don't want the parent thread modifying oldMap while we are
// iterating over it
synchronized
(
oldMap
)
{
newMap
.
putAll
(
oldMap
);
}
}
copyOnInheritThreadLocal
.
set
(
newMap
);
return
newMap
;
}
/**
* Put a context value (the <code>val</code> parameter) as identified with the
* <code>key</code> parameter into the current thread's context map. Note that
* contrary to log4j, the <code>val</code> parameter can be null.
* <p/>
* <p/>
* If the current thread does not have a context map it is created as a side
* effect of this call.
*
* @throws IllegalArgumentException in case the "key" parameter is null
*/
@Override
public
void
put
(
String
key
,
String
val
)
{
if
(
key
==
null
)
{
throw
new
IllegalArgumentException
(
"key cannot be null"
);
}
Map
<
String
,
String
>
oldMap
=
copyOnInheritThreadLocal
.
get
();
Integer
lastOp
=
getAndSetLastOperation
(
WRITE_OPERATION
);
if
(
wasLastOpReadOrNull
(
lastOp
)
||
oldMap
==
null
)
{
Map
<
String
,
String
>
newMap
=
duplicateAndInsertNewMap
(
oldMap
);
newMap
.
put
(
key
,
val
);
}
else
{
oldMap
.
put
(
key
,
val
);
}
}
/**
* Remove the the context identified by the <code>key</code> parameter.
* <p/>
*/
@Override
public
void
remove
(
String
key
)
{
if
(
key
==
null
)
{
return
;
}
Map
<
String
,
String
>
oldMap
=
copyOnInheritThreadLocal
.
get
();
if
(
oldMap
==
null
)
{
return
;
}
Integer
lastOp
=
getAndSetLastOperation
(
WRITE_OPERATION
);
if
(
wasLastOpReadOrNull
(
lastOp
))
{
Map
<
String
,
String
>
newMap
=
duplicateAndInsertNewMap
(
oldMap
);
newMap
.
remove
(
key
);
}
else
{
oldMap
.
remove
(
key
);
}
}
/**
* Clear all entries in the MDC.
*/
@Override
public
void
clear
()
{
lastOperation
.
set
(
WRITE_OPERATION
);
copyOnInheritThreadLocal
.
remove
();
}
/**
* Get the context identified by the <code>key</code> parameter.
* <p/>
*/
@Override
public
String
get
(
String
key
)
{
final
Map
<
String
,
String
>
map
=
copyOnInheritThreadLocal
.
get
();
if
((
map
!=
null
)
&&
(
key
!=
null
))
{
return
map
.
get
(
key
);
}
else
{
return
null
;
}
}
/**
* Get the current thread's MDC as a map. This method is intended to be used
* internally.
*/
public
Map
<
String
,
String
>
getPropertyMap
()
{
lastOperation
.
set
(
MAP_COPY_OPERATION
);
return
copyOnInheritThreadLocal
.
get
();
}
/**
* Returns the keys in the MDC as a {@link Set}. The returned value can be
* null.
*/
public
Set
<
String
>
getKeys
()
{
Map
<
String
,
String
>
map
=
getPropertyMap
();
if
(
map
!=
null
)
{
return
map
.
keySet
();
}
else
{
return
null
;
}
}
/**
* Return a copy of the current thread's context map. Returned value may be
* null.
*/
@Override
public
Map
<
String
,
String
>
getCopyOfContextMap
()
{
Map
<
String
,
String
>
hashMap
=
copyOnInheritThreadLocal
.
get
();
if
(
hashMap
==
null
)
{
return
null
;
}
else
{
return
new
HashMap
<>(
hashMap
);
}
}
@Override
public
void
setContextMap
(
Map
<
String
,
String
>
contextMap
)
{
lastOperation
.
set
(
WRITE_OPERATION
);
Map
<
String
,
String
>
newMap
=
Collections
.
synchronizedMap
(
new
HashMap
<>());
newMap
.
putAll
(
contextMap
);
// the newMap replaces the old one for serialisation's sake
copyOnInheritThreadLocal
.
set
(
newMap
);
}
}
zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories
浏览文件 @
fc469f04
org.springframework.context.ApplicationContextInitializer=\
com.central.log.config.TtlMDCAdapterInitializer
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.log.config.LogAutoConfigure
com.central.log.config.LogAutoConfigure
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录