ApiBoot Logging使用RestTemplate透传链路信息

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 使用RestTempalte透传日志链路信息

搭建Logging Admin

我们需要搭建Logging Admin服务,用于接收业务服务上报的请求日志信息。

添加ApiBoot统一版本

由于本章采用是Maven 多模块的方式构建源码,所以我们只需要将ApiBoot统一版本的依赖配置在root项目的pom.xml内,如下所示:

<properties>
  <java.version>1.8</java.version>
  <!--ApiBoot版本号-->
  <api.boot.version>2.1.5.RELEASE</api.boot.version>
</properties>
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.minbox.framework</groupId>
      <artifactId>api-boot-dependencies</artifactId>
      <version>${api.boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

接下来我们营造本篇文章的模拟场景查询用户基本信息时一并查询出用户的账号余额

创建账户服务

创建一个名为account-serviceSpringBoot项目。

添加相关依赖

在项目pom.xml配置文件内添加相关依赖,如下所示:

<dependencies>
  <!--SpringBoot Web-->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <!--ApiBoot Logging-->
  <dependency>
    <groupId>org.minbox.framework</groupId>
    <artifactId>api-boot-starter-logging</artifactId>
  </dependency>
</dependencies>

配置上报的Logging Admin

application.yml配置文件内添加请求日志上报的Logging Admin地址,如下所示:

spring:
  application:
    name: account-service
server:
  port: 9090

api:
  boot:
    logging:
      # 控制台打印请求日志
      show-console-log: true
      # 美化请求日志
      format-console-log-json: true
      # Logging Admin地址
      admin:
        server-address: 127.0.0.1:8081
注意: server-address配置参数不需要添加 http://前缀

启用Logging Client

添加完成依赖后我们通过@EnableLoggingClient注解来启用ApiBoot Logging,在AccountServiceApplication类上添加如下所示:

/**
 * 账户服务
 *
 * @author 恒宇少年
 */
@SpringBootApplication
@EnableLoggingClient
public class AccountServiceApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(AccountServiceApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(AccountServiceApplication.class, args);
        logger.info("{}服务启动成功.", "账户");
    }
}
@EnableLoggingClient注解就实例化部分 ApiBoot Logging内部所需要的类,将实例放置到 Spring IOC容器内。

查询账户余额代码实现

我们创建一个名为AccountController的控制器来提供查询账户的余额信息,代码实现如下所示:

/**
 * 账户服务实现
 *
 * @author 恒宇少年
 */
@RestController
@RequestMapping(value = "/account")
public class AccountController {

    /**
     * 示例,内存账户列表
     */
    static final HashMap<Integer, Double> ACCOUNTS = new HashMap() {{
        put(1, 1233.22);
        put(2, 69269.22);
    }};

    /**
     * 获取指定账户的余额
     *
     * @param accountId
     * @return
     */
    @GetMapping(value = "/{accountId}")
    public Double getBalance(@PathVariable("accountId") Integer accountId) {
        return ACCOUNTS.get(accountId);
    }
}
至此我们的账户服务已经编写完成,下面我们来编写 用户服务

创建用户服务

我们来创建一个名为user-serviceSpringBoot项目。

添加相关依赖

在项目pom.xml配置文件内添加相关依赖,如下所示:

<dependencies>
  <!--SpringBoot Web-->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <!--ApiBoot Logging-->
  <dependency>
    <groupId>org.minbox.framework</groupId>
    <artifactId>api-boot-starter-logging</artifactId>
  </dependency>
</dependencies>

配置上报的Logging Admin

本章我们使用指定Logging Admin地址的方式配置,修改application.yml配置文件如下所示:

spring:
  application:
    name: user-service
server:
  port: 9091

api:
  boot:
    logging:
      # 控制台打印请求日志
      show-console-log: true
      # 美化请求日志
      format-console-log-json: true
      # Logging Admin地址
      admin:
        server-address: 127.0.0.1:8081

启用Logging Client

添加完依赖后我们需要在XxxApplication入口类上添加@EnableLoggingClient注解来启用ApiBoot Logging,如下所示:

/**
 * 用户服务
 *
 * @author 恒宇少年
 */
@SpringBootApplication
@EnableLoggingClient
public class UserServiceApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(UserServiceApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
        logger.info("{}服务启动成功.", "用户");
    }
}

实例化RestTemplate对象

user-service需要访问账户服务获取当前用户的余额,所以我们需要在user-service内实例化RestTemplate,这样我们才可以通过RestTemplate访问获取用户账户余额信息,我们直接在UserServiceApplication类内添加实例,如下所示:

    /**
     * 实例化RestTemplate
     *
     * @return {@link RestTemplate}
     */
    @Bean
    @ConditionalOnMissingBean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

注解解释:

  • @ConditionalOnMissingBean:这是SpringBoot条件注入其中的一个注解,表示当IOC容器内不存在RestTemplate类型的实例时才会去执行restTemplate()方法创建对象。

查询用户信息代码实现

/**
 * 用户基本信息控制器
 *
 * @author 恒宇少年
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {
    /**
     * 示例,用户列表
     */
    static final HashMap<Integer, User> USERS = new HashMap() {{
        put(1, new User(1, "恒宇少年"));
        put(2, new User(2, "于起宇"));
    }};
    /**
     * 注入RestTemplate
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取用户基本信息
     *
     * @param userId 用户编号
     * @return
     */
    @GetMapping(value = "/{userId}")
    public User getUserInfo(@PathVariable("userId") Integer userId) {
        ResponseEntity<Double> responseEntity = restTemplate.getForEntity("http://localhost:9090/account/{accountId}", Double.class, userId);
        Double balance = responseEntity.getBody();
        User user = USERS.get(userId);
        if (ObjectUtils.isEmpty(user)) {
            throw new RuntimeException("用户:" + userId + ",不存在.");
        }
        user.setBalance(balance);
        return user;
    }

    @Data
    public static class User {
        private Integer id;
        private String name;
        private Double balance;

        public User(Integer id, String name) {
            this.id = id;
            this.name = name;
        }
    }
}

我们所需要的两个服务都已经编写完成,下面我们来测试RestTemplate是可以透传ApiBoot Logging的链路信息?

运行测试

依次启动logging-admin > user-service > account-service

测试点:透传链路信息

我们使用curl命令访问user-service提供的地址/user,如下所示:

➜ ~ curl http://localhost:9091/user/1
{"id":1,"name":"恒宇少年","balance":1233.22}

下面我看来看下logging-admin控制台接收到的请求日志。

接收user-service请求日志

Receiving Service: 【user-service -> 127.0.0.1】, Request Log Report,Logging Content:[
    {
        "endTime":1573032865311,
        "httpStatus":200,
        "requestBody":"",
        "requestHeaders":{
            "host":"localhost:9091",
            "user-agent":"curl/7.64.1",
            "accept":"*/*"
        },
        "requestIp":"0:0:0:0:0:0:0:1",
        "requestMethod":"GET",
        "requestParam":"{}",
        "requestUri":"/user/1",
        "responseBody":"{\"id\":1,\"name\":\"恒宇少年\",\"balance\":1233.22}",
        "responseHeaders":{},
        "serviceId":"user-service",
        "serviceIp":"127.0.0.1",
        "servicePort":"9091",
        "spanId":"f8cff018-42d5-481f-98df-c19b7196b3c3",
        "startTime":1573032865130,
        "timeConsuming":181,
        "traceId":"16ad1dd4-beaa-4110-b4b7-fc7d952d9a57"
    }
]

接收account-service请求日志

Receiving Service: 【account-service -> 127.0.0.1】, Request Log Report,Logging Content:[
    {
        "endTime":1573032865309,
        "httpStatus":200,
        "parentSpanId":"f8cff018-42d5-481f-98df-c19b7196b3c3",
        "requestBody":"",
        "requestHeaders":{
            "minbox-logging-x-parent-span-id":"f8cff018-42d5-481f-98df-c19b7196b3c3",
            "minbox-logging-x-trace-id":"16ad1dd4-beaa-4110-b4b7-fc7d952d9a57",
            "host":"localhost:9090",
            "connection":"keep-alive",
            "accept":"application/json, application/*+json",
            "user-agent":"Java/1.8.0_211"
        },
        "requestIp":"127.0.0.1",
        "requestMethod":"GET",
        "requestParam":"{}",
        "requestUri":"/account/1",
        "responseBody":"1233.22",
        "responseHeaders":{},
        "serviceId":"account-service",
        "serviceIp":"127.0.0.1",
        "servicePort":"9090",
        "spanId":"63b18b40-5718-431c-972f-78956ce78380",
        "startTime":1573032865307,
        "timeConsuming":2,
        "traceId":"16ad1dd4-beaa-4110-b4b7-fc7d952d9a57"
    }
]
  • 当我们访问user-service服务内的/user路径时,因为是第一次访问ApiBoot Logging会主动创建traceId(链路编号)、spanId(单元编号),因为没有上级单元所以parentSpanIdnull.
  • 而通过查看account-service服务上报的请求日志时,可以看到ApiBoot Logging相关的链路信息是通过HttpHeader的方式进行传递的

    • minbox-logging-x-trace-id -> 链路编号
    • minbox-logging-x-parent-span-id -> 上级单元编号

敲黑板,划重点

ApiBoot Logging在内部自动化实现了RestTemplate的拦截器配置,所以我们只需要创建实例就可以,而不需要主动去配置拦截器信息,具体源码请访问org.minbox.framework.logging.client.http.rest.LoggingRestTemplateInterceptor查看。

不管你一次请求跨度几个服务,都可以将请求入口生成的链路信息进行依次传递,而上下级关系则是根据parentSpanIdspanId进行绑定的。

代码示例

如果您喜欢本篇文章请为源码仓库点个Star,谢谢!!!
本篇文章示例源码可以通过以下途径获取,目录为apiboot-logging-using-resttemplate-transparent-traceid

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
Java Spring
Springboot starter开发之traceId请求日志链路追踪
能标识一次请求的完整流程,包括日志打印、响应标识等,以便于出现问题可以快速定位并解决问题。
1777 0
Springboot starter开发之traceId请求日志链路追踪
|
3月前
|
消息中间件 监控 搜索推荐
OpenFeign日志组件Logger原理与应用
该文章详细解释了如何在OpenFeign中配置并使用请求和响应的GZIP压缩功能。
|
4月前
|
Java 微服务 Spring
SpringCloud gateway自定义请求的 httpClient
SpringCloud gateway自定义请求的 httpClient
197 3
|
5月前
|
JSON Java API
技术笔记:springboot项目使用拦截器实现一个简单的网关请求透传
技术笔记:springboot项目使用拦截器实现一个简单的网关请求透传
239 0
SpringCloud OpenFeign 服务调用传递 token
通常微服务对于用户认证信息解析有两种方案 在 gateway 就解析用户的 token 然后路由的时候把 userId 等相关信息添加到 header 中传递下去。 在 gateway 直接把 token 传递下去,每个子微服务器自己在过滤器解析 token
|
存储 Java 中间件
SpringBoot+MDC链路追踪trace_id丢失
前言 trace_id是用来标识同一个请求的唯一标识,不管请求经过多少服务,都可以通过tracid排查对应模块的日志信息找到对应请求的一些细节,是排查问题的一个重要线索。
470 0
|
监控 Java 微服务
SpringCloud Day09--分布式请求链路跟踪(SpringCloud Sleuth)
SpringCloud Day09--分布式请求链路跟踪(SpringCloud Sleuth)
SpringCloud Day09--分布式请求链路跟踪(SpringCloud Sleuth)
|
监控 Java 开发工具
使用ApiBoot Logging进行统一管理请求日志
`ApiBoot Logging`通过集成`minbox-logging`来进行管理每一次请求的日志信息,包含`头信息`、`参数`、`主体内容`、`路径`、发生的`服务器`相关信息等,根据接口的响应状态还可以记录响应的头信息、响应的内容以及发生异常时的`堆栈信息`。
|
Java 微服务
自定义ApiBoot Logging链路以及单元ID
`ApiBoot Logging`会为每一个请求都对应创建链路编号(`TraceID`)以及单元编号(`SpanID`),用于归类每一次请求日志,通过一个链路下日志单元的`Parent SpanID`可以进行上下级关系的梳理。
自定义ApiBoot Logging链路以及单元ID
|
监控 Java 微服务
SpringCloud Sleuth分布式请求链路跟踪
在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败。
SpringCloud Sleuth分布式请求链路跟踪