1.新建项目

利用idea创建一个父项目,三个子项目,其中一个项目为生产者,一个项目为消费者,一个为接口等公共服务项目,生产者和消费者需要有web依赖,可以作为tomcat容器启动。
2.项目依赖
<dependencies>
<dependency>
<groupId>org
.apache
.dubbo
</groupId
>
<artifactId>dubbo
–spring
–boot
–starter
</artifactId
>
<version>2.7.6</version
>
</dependency
>
<!— zk的依赖
—>
<dependency>
<groupId>org
.apache
.dubbo
</groupId
>
<artifactId>dubbo
–dependencies
–zookeeper
</artifactId
>
<version>2.7.6</version
>
<type>pom
</type
>
<exclusions>
<exclusion>
<groupId>org
.slf4j
</groupId
>
<artifactId>slf4j
–log4j12
</artifactId
>
</exclusion
>
</exclusions
>
</dependency
>
<dependency>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
–boot
–starter
–aop
</artifactId
>
<scope>test
</scope
>
</dependency
>
<dependency>
<groupId>org
.aspectj
</groupId
>
<artifactId>aspectjweaver
</artifactId
>
</dependency
>
3.在facade项目中新建接口

4.编写生产者
4.1 增加dubbo配置
server
.port
=8081
dubbo
.registry
.address
=zookeeper
://localhost
:2181
dubbo
.protocol
.name
=dubbo
dubbo
.protocol
.port
=20880
dubbo
.registry
.timeout
=30000
dubbo
.application
.name
=dubbo
–provider
–ll
4.2 编写生产者dubbo filter
public class ProviderFilter implements Filter {
@Override
public Result
invoke(Invoker
<?> invoker
, Invocation invocation
) throws RpcException
{
Object threadName
= invocation
.getAttachment(“ThreadName”);
if(null
!=threadName
){
Thread thread
= Thread
.currentThread();
thread
.setName(threadName
.toString());
}
return invoker
.invoke(invocation
);
}
}
注意:此处Filter 是dubbo的filter,不是servlet的filter
这里代码的目的是将从消费端传来的线程名称设置为线程名称
在resources目录下新建META-INF/dubbo/com.alibaba.dubbo.rpc.Filter 文件
即新增目录META-INF/dubbo和文件 com.alibaba.dubbo.rpc.Filter
在文件中增加,等号后面为实现dubbo filter的实现类路径
providerFilter=com.dubbo.spring.provider.filter.ProviderFilter
4.3编写dubbo生产者实现类
@Service(filter
= {“providerFilter”})
public class DemoServiceImpl implements IDemoService {
public Logger LOGGER
= LoggerFactory
.getLogger(DemoServiceImpl
.class);
@Override
public String
getName() {
LOGGER
.info(“provider ThreadName : “+Thread
.currentThread().getName());
return “dubbo-test”;
}
}
5.编写消费者
5.1编写消费者filter
public class DubboFilter implements Filter {
@Override
public Result
invoke(Invoker
<?> invoker
, Invocation invocation
) throws RpcException
{
String name
= Thread
.currentThread().getName();
invocation
.setAttachment(“ThreadName”,name
);
return invoker
.invoke(invocation
);
}
}
此处是将线程名称放入到attachment中,attachment底层是hashmap,后续使用dubbo请求生产者时,会把attachment给到生产者,故在生产中中可以通过key ThreadName来获取消费者端的线程名称
在resources目录下新建META-INF/dubbo/com.alibaba.dubbo.rpc.Filter 文件
即新增目录META-INF/dubbo和文件 com.alibaba.dubbo.rpc.Filter
在文件中增加,等号后面为实现dubbo filter的实现类路径
consumerFilter=com.dubbo.spring.consumer.filter.DubboFilter
5.2 编写response对象
public class Response implements Serializable {
private static final long serialVersionUID
= –3186818832535757509L
;
private String code
;
private String message
;
private Object result
;
private String index
;
public String
getCode() {
return code
;
}
public void setCode(String code
) {
this.code
= code
;
}
public String
getMessage() {
return message
;
}
public void setMessage(String message
) {
this.message
= message
;
}
public Object
getResult() {
return result
;
}
public void setResult(Object result
) {
this.result
= result
;
}
public String
getIndex() {
return index
;
}
public void setIndex(String index
) {
this.index
= index
;
}
}
此response为web端返回到页面统一对象
5.3 编写aop切面
@Aspect
@Component
public class AopContext {
@Before(“execution(* com.dubbo.spring..*.*(..))”)
public void before(){
Thread thread
= Thread
.currentThread();
thread
.setName(UUIDUtil
.getUUID());
}
@Around(“execution(* com.dubbo.spring..*.*(..))”)
public Object
around(ProceedingJoinPoint pjp
){
Response response
=new Response();
try {
Object proceed
= pjp
.proceed();
if(proceed
instanceof Response){
response
=(Response
) proceed
;
response
.setIndex(Thread
.currentThread().getName());
}
} catch (Throwable throwable
) {
throwable
.printStackTrace();
}
return response
;
}
}
1.before是在请求进入时给线程设置名称,为随机生成的uuid
2.around是环绕通知,在执行完之后,在返回的结果中将线程名称设置进去,便于以后异常追踪
5.4 编写web
@RestController
public class WebController {
private Logger LOGGER
= LoggerFactory
.getLogger(WebController
.class);
@Reference(filter
= {“consumerFilter”})
private IDemoService iDemoService
;
@GetMapping(“/getName”)
public Response
getName(){
LOGGER
.info(“consumer ThreadName : “+Thread
.currentThread().getName());
String name
= iDemoService
.getName();
Response response
=new Response();
response
.setResult(name
);
response
.setCode(“1001”);
response
.setMessage(“success”);
return response
;
}
}
请求结果

此处为postman响应的,index 为1ca55cb7a17148879923265b89102ccf
生产者线程名称:

消费者线程名称:

可以看到从web页面到生产者,消费者,都有一个全局唯一id进行贯穿,如果在web页面提示有异常时,可以通过这个uuid进行日志追踪
到此这篇关于springboot整合dubbo设置全局唯一ID进行日志追踪的文章就介绍到这了。