dubbo服务链路跟踪方式

网友投稿 243 2022-10-10


dubbo服务链路跟踪方式

目前很多业务使用微服务架构,服务模块划分有这2种方式:

服务功能划分

业务划分

不管哪种方式,一次接口调用都需要多个服务协同完成,其中一个服务出现问题,都会导致最终失败,虽然有logback + kafka + ELK 这样的神器架构,但是定位问题也很麻烦,如果在整个链路中,可以通过一个唯一ID(traceId)跟踪本次服务调用,就可以在ELK中查找当前traceId来定位问题。

一、案例

1、案例结构

pratices-demo-provider-core:定义服务接口

pratices-demo-provider:具体实现

pratices-demo-consumer-core:服务消费者,同时也是服务提供者

pratices-demo-consumer:具体实现

pratices-demo-web:提供http服务

pratices-demo-trace:本案例的核心模块,在服务调用时拦截,设置traceId,跟踪本次服务调用

2、pratices-demo

2.1、pom.xml

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

pom

pratices-demo-consumer

pratices-demo-provider

pratices-demo-provider-core

pratices-demo-consumer-core

pratices-demo-web

pratices-demo-trace

org.springframework.boot

spring-boot-starter-parent

2.1.4.RELEASE

com.cn.dl

pratices-demo

0.0.1-SNAPSHOT

pratices-demo

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-autoconfigure

com.alibaba

dubbo

2.6.0

org.springframework

spring

ch.qos.logback

logback-core

ch.qos.logback

logback-access

ch.qos.logback

gGwJxnPTh logback-classic

org.slf4j

slf4j-api

org.apache.zookeeper

zookeeper

3.4.10

com.101tec

zkclient

0.10

slf4j-log4j12

org.slf4j

org.springframework.boot

spring-boot-maven-plugin

spring-milestones

Spring Milestones

https://repo.spring.io/milestone

spring-snapshots

Spring Snapshots

https://repo.spring.io/snapshot

true

spring-milestones

Spring Milestones

https://repo.spring.io/milestone

spring-snapshots

Spring Snapshots

https://repo.spring.io/snapshot

true

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

pom

pratices-demo-consumer

pratices-demo-provider

pratices-demo-provider-core

pratices-demo-consumer-core

pratices-demo-web

pratices-demo-trace

org.springframework.boot

spring-boot-starter-parent

2.1.4.RELEASE

com.cn.dl

pratices-demo

0.0.1-SNAPSHOT

pratices-demo

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-autoconfigure

com.alibaba

dubbo

2.6.0

org.springframework

spring

ch.qos.logback

logback-core

ch.qos.logback

logback-access

ch.qos.logback

gGwJxnPTh logback-classic

org.slf4j

slf4j-api

org.apache.zookeeper

zookeeper

3.4.10

com.101tec

zkclient

0.10

slf4j-log4j12

org.slf4j

org.springframework.boot

spring-boot-maven-plugin

spring-milestones

Spring Milestones

https://repo.spring.io/milestone

spring-snapshots

Spring Snapshots

https://repo.spring.io/snapshot

true

spring-milestones

Spring Milestones

https://repo.spring.io/milestone

spring-snapshots

Spring Snapshots

https://repo.spring.io/snapshot

true

3、pratices-demo-provider-core

3.1、ProviderService

package com.cn.dl;

/**

* Created by yanshao on 2019-09-04.

*/

public interface ProviderService {

String sayHello(String name);

}

4、pratices-demo-provider

4.1、ProviderServiceImpl

package com.cn.dl.provider.impl;

import com.alibaba.dubbo.config.annotation.Service;

import com.cn.dl.ProviderService;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

/**

* Created by yanshao on 2019-09-04.

*/

@Service

public class ProviderServiceImpl implements ProviderService {

private static final Logger log = LoggerFactory.getLogger(ProviderServiceImpl.class);

@Override

public String sayHello(String name) {

log.info("providerServiceImpl 服务提供 traceId:{},sayHello:{}", MDC.get("traceId"),name);

return "hello " + name ;

}

}

4.2、dubbo-provider.properties 配置文件

# dubbo-provider.properties

dubbo.application.name=service2

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.protocol.name=dubbo

dubbo.protocol.port=50010

dubbo.consumer.timeout=5000

4.3、ProviderMain服务启动类

注意:启动dubbo服务不需要暴露http服务

package com.cn.dl;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.boot.WebApplicationType;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.builder.SpringApplicationBuilder;

import org.springframework.context.annotation.PropertySource;

import java.util.concurrent.locks.LockSupport;

/**

* Created by yanshao on 2019-09-04.

*/

@EnableDubbo(scanBasePackages = "com.cn.dl*")

@PropertySource("classpath:/dubbo-provider.properties")

@SpringBootApplication

public class ProviderMain{

private static final Logger log = LoggerFactory.getLogger(ProviderMain.class);

/**

* 启动dubbo服务,不需要提供web服务,但是默认有8080端口,通过一下方式可以不暴露web服务

*

* 1、在application.properties加上一下配置

*

* spring:

* main:

* allow-bean-definition-overriding: true

* web-application-type: none

*

* 2、修改启动类

* new SpringApplicationBuilder(ProviderMain .class)

* .web(WebApplicationType.NONE)

* .run(args)

* */

public static void main(String[] args) {

new SpringApplicationBuilder(ProviderMain.class).web(WebApplicationType.NONE).run(args);

log.info("ProviderMain 启动了");

LockSupport.park();

}

}

@EnableDubbo(scanBasePackages = "com.cn.dl*")

扫描Dubbo的服务提供者以及Dubbo的服务消费者,一定要注意@EnableDubbo和@SpringBootApplication的先后次序;

@PropertySource("classpath:/dubbo-provider.properties")

加载配置文件到上下文环境变量。

5、pratices-demo-consumer-core

5.1、ConsumerService

package com.cn.dl;

/**

* Created by yanshao on 2019-09-04.

*/

public interface ConsumerService {

String toSayHello(String name);

int getRandomInt();

}

6、pratices-demo-consumer

6.1、ConsumerServiceImpl

package com.cn.dl.consumer.impl;

import com.alibaba.dubbo.config.annotation.Reference;

import com.alibaba.dubbo.config.annotation.Service;

import com.cn.dl.ConsumerService;

import com.cn.dl.ProviderService;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

import java.util.Random;

/**

* Created by yanshao on 2019-09-04.

*/

@Service

public class ConsumerServiceImpl implements ConsumerService {

private static final Logger log = LoggerFactory.getLogger(ConsumerServiceImpl.class);

@Reference

private ProviderService providerService;

@Override

public String toSayHello(String name) {

String sayHello = providerService.sayHello(name);

log.info("ConsumerServiceImpl >>>> traceId:{},sayHello:{}", MDC.get("traceId"),sayHello);

return sayHello;

}

@Override

public int getRandomInt() {

return new Random().nextInt(100);

}

}

6.2、dubbo-consumer.properties

dubbo.application.name=service1

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.protocol.name=dubbo

dubbo.protocol.port=50020

dubbo.consumer.timeout=5000

6.3、ConsumerMain

package com.cn.dl;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;

import org.springframework.boot.WebApplicationType;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.builder.SpringApplicationBuilder;

import org.springframework.context.annotation.PropertySource;

import java.util.concurrent.locks.LockSupport;

/**

* Created by yanshao on 2019-09-04.

*/

@EnableDubbo(scanBasePackages = "com.cn.dl*")

@PropertySource("classpath:/dubbo-consumer.properties")

@SpringBootApplication

public class ConsumerMain {

public static void main(String[] args) {

new SpringApplicationBuilder(ConsumerMain.class).web(WebApplicationType.NONE).run(args);

LockSupport.park();

}

}

7、pratices-demo-web

7.1、WebTraceFilter

定义web拦截器,拦截所有请求,生成唯一ID

package com.cn.dl.webTrace;

import com.cn.dl.utils.TraceUtil;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import static com.cn.dl.config.TraceConfig.TRACE_ID;

/**

* Created by yanshao on 2019-09-04.

*/

public class WebTraceFilter implements Filter {

private static final Logger log = LoggerFactory.getLogger(WebTraceFilter.class);

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

if (! (servletRequest instanceof HttpServletRequest) || ! (servletResponse instanceof HttpServletResponse)) {

throw new ServletException("只支持http请求");

}

try {

String traceId = TraceUtil.getTraceId();

log.info("WebTraceFilter traceId:{}",traceId);

MDC.put(TRACE_ID,traceId);

filterChain.doFilter(servletRequest, servletResponse);

} finally {

MDC.remove(TRACE_ID);

}

}

}

7.2、TraceUtil

package com.cn.dl.utils;

import java.util.UUID;

/**

* Created by yanshao on 2019-09-04.

*/

public class TraceUtil {

public static String getTraceId(){

return UUID.randomUUID().toString().replace("-","");

}

public static void main(String[] args) {

System.out.println(getTraceId());

}

}

7.3、TraceConfig

package com.cn.dl.config;

/**

* Created by yanshao on 2019-09-04.

*/

public interface TraceConfig {

String TRACE_ID = "traceId";

}

7.4、RpcProviderInterceptor

package com.cn.dl.rpcTrace;

import com.alibaba.dubbo.common.Constants;

import com.alibaba.dubbo.common.extension.Activate;

import com.alibaba.dubbo.rpc.*;

import com.cn.dl.utils.TraceUtil;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

import org.springframework.util.StringUtils;

import java.util.Map;

import static com.cn.dl.config.TraceConfig.TRACE_ID;

/**

* Created by yanshao on 2019-09-04.

*/

@Activate(group = Constants.PROVIDER)

public class RpcProviderInterceptor implements Filter {

private static final Logger log = LoggerFactory.getLogger(RpcProviderInterceptor.class);

@Override

public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {

Result result;

try {

Map at = invocation.getAttachments();

MDC.put(TRACE_ID, ! StringUtils.isEmpty(at.get(TRACE_ID)) ? at.get(TRACE_ID): TraceUtil.getTraceId());

result = invoker.invoke(invocation);

} catch (Exception e) {

log.error("RpcProviderInterceptor 异常",e);

throw e;

} finally {

MDC.remove(TRACE_ID);

}

return result;

}

}

7.5、RpcConsumerInterceptor

package com.cn.dl.rpcTrace;

import com.alibaba.dhttp://ubbo.common.Constants;

import com.alibaba.dubbo.common.extension.Activate;

import com.alibaba.dubbo.rpc.*;

import com.cn.dl.utils.TraceUtil;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

import java.util.Map;

import static com.cn.dl.config.TraceConfig.TRACE_ID;

/**

* Created by yanshao on 2019-09-04.

*/

@Activate(group = Constants.CONSUMER)

public class RpcConsumerInterceptor implements Filter {

prhttp://ivate static final Logger log = LoggerFactory.getLogger(RpcProviderInterceptor.class);

@Override

public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {

Result result;

try {

Map at = invocation.getAttachments();

if (MDC.get(TRACE_ID) == null) {

MDC.put(TRACE_ID,TraceUtil.getTraceId());

}

at.put(TRACE_ID, MDC.get(TRACE_ID));

result = invoker.invoke(invocation);

}catch (Exception e){

log.error("RpcConsumerInterceptor 异常",e);

throw e;

}

return result;

}

}

7.6、RpcProviderInterceptor

package com.cn.dl.rpcTrace;

import com.alibaba.dubbo.common.Constants;

import com.alibaba.dubbo.common.extension.Activate;

import com.alibaba.dubbo.rpc.*;

import com.cn.dl.utils.TraceUtil;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.slf4j.MDC;

import org.springframework.util.StringUtils;

import java.util.Map;

import static com.cn.dl.config.TraceConfig.TRACE_ID;

/**

* Created by yanshao on 2019-09-04.

*/

@Activate(group = Constants.PROVIDER)

public class RpcProviderInterceptor implements Filter {

private static final Logger log = LoggerFactory.getLogger(RpcProviderInterceptor.class);

@Override

public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {

Result result;

try {

Map at = invocation.getAttachments();

MDC.put(TRACE_ID, ! StringUtils.isEmpty(at.get(TRACE_ID)) ? at.get(TRACE_ID): TraceUtil.getTraceId());

result = invoker.invoke(invocation);

} catch (Exception e) {

log.error("RpcProviderInterceptor 异常",e);

throw e;

} finally {

MDC.remove(TRACE_ID);

}

return result;

}

}

然后在resources下创建META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,将扩展的拦截器添加到dubbo调用链中

consumerTraceFilter=com.cn.dl.rpcTrace.RpcConsumerInterceptor

providerTraceFilter=com.cn.dl.rpcTrace.RpcProviderInterceptor

8、pratices-demo-web

8.1、TraceInterceptor注册web拦截器

package com.cn.dl.config;

import com.cn.dl.webTrace.WebTraceFilter;

import org.springframework.boot.SpringBootConfiguration;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import javax.annotation.Resource;

import javax.servlet.Filter;

/**

* Created by yanshao on 2019-09-04.

*/

@SpringBootConfiguration

public class TraceInterceptor {

@Bean(name = "webTraceFilter")

public WebTraceFilter getWebTraceFilter(){

return new WebTraceFilter();

}

@Bean

@Resource

public FilterRegistrationBean traceFilterRegistration(Filter webTraceFilter) {

FilterRegistrationBean registration = new FilterRegistrationBean<>();

registration.setFilter(webTraceFilter);

registration.addUrlPatterns("/*");

registration.setName("webTraceFilter");

registration.setOrder(1);

return registration;

}

}

8.2、dubbo.properties

dubbo.application.name=consumer-service

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.consumer.timeout=5000

8.3、DemoWebController

package com.cn.dl.controller;

import com.alibaba.dubbo.config.annotation.Reference;

import com.cn.dl.ConsumerService;

import org.springframework.web.bind.annotation.*;

/**

* Created by yanshao on 2019-09-04.

*/

@RestController

public class DemoWebController {

@Reference

private ConsumerService consumerService;

@PostMapping("sayHello")

public String sayHello(@RequestParam("name") String name){

return consumerService.toSayHello(name);

}

@GetMapping("getRandomInt")

public int getRandomInt(){

return consumerService.getRandomInt();

}

}

8.4、StartWeb

package com.cn.dl;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.PropertySource;

/**

* Created by yanshao on 2019-09-04.

*/

@EnableDubbo(scanBasePackages = "com.cn.dl*")

@PropertySource("classpath:/dubbo.properties")

@SpringBootApplication

public class StartWeb {

public static void main(String[] args) {

SpringApplication.run(StartWeb.class,args);

}

}

9、分别启动providerMain、consumerMain、startWeb


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:HSRP双机热备工作原理与配置(双机热备技术的功能)
下一篇:checkpoint R80初始化安装和smartconsole安装(checkpoint 3ds)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~