使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法
创始人
2024-11-17 14:42:24
0次

1.新建项目

使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法

利用idea创建一个父项目,三个子项目,其中一个项目为生产者,一个项目为消费者,一个为接口等公共服务项目,生产者和消费者需要有web依赖,可以作为tomcat容器启动。

2.项目依赖


    
      org.apache.dubbo
      dubbo-spring-boot-starter
      2.7.6
    

    
    
      org.apache.dubbo
      dubbo-dependencies-zookeeper
      2.7.6
      pom
      
        
          org.slf4j
          slf4j-log4j12
        
      
    
    
      org.springframework.boot
      spring-boot-starter-aop
      test
    
    
      org.aspectj
      aspectjweaver
    

3.在facade项目中新建接口

使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法

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

请求结果

使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法

此处为postman响应的,index 为1ca55cb7a17148879923265b89102ccf

生产者线程名称:

使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法

消费者线程名称:

使用springboot整合dubbo设置全局唯一ID进行日志追踪的方法

可以看到从web页面到生产者,消费者,都有一个全局唯一id进行贯穿,如果在web页面提示有异常时,可以通过这个uuid进行日志追踪

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...