0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ApiBoot Logging使用Spring Cloud Openfeign透传链路信息

电子设计 来源:电子设计 作者:电子设计 2020-12-10 22:05 次阅读

ApiBoot Logging可以无缝整合SpringCloud来采集请求日志,目前支持RestTemplateOpenfeign两种方式,我们本章来讲解下在使用Openfeign完成服务之间请求相互调用的一条链路请求日志是否可以都采集到。

搭建Eureka Server

我们先来搭建一个Eureka Server,请访问【搭建服务注册中心Eureka Server】文章内容查看具体搭建流程。

搭建Logging Admin

我们需要搭建一个Logging Admin用于接收Logging Client上报的请求日志,请访问【ApiBoot Logging整合SpringCloud Eureka负载均衡上报日志】查看具体的搭建流程。

我们本章来模拟提交订单的业务逻辑,涉及到两个服务,分别是:商品服务订单服务,接下来我们需要来创建这两个服务。

添加ApiBoot & SpringCloud统一版本

由于是采用Maven 多模块项目,存在继承关系,我们只需要在root模块添加版本依赖即可,其他子模块就可以直接使用,如下所示:

1.82.1.5.RELEASEGreenwich.SR3org.minbox.frameworkapi-boot-dependencies${api.boot.version}pomimportorg.springframework.cloudspring-cloud-dependencies${spring.cloud.version}pomimport

创建公共Openfeign接口定义

学习过Openfeign的同学应该都知道,Openfeign可以继承实现,我们只需要创建一个公共的服务接口定义,在实现该接口的服务进行业务实现,在调用该接口的地方直接注入即可。
下面我们创建一个名为common-openfeign的公共依赖项目,pom.xml添加依赖如下所示:

org.springframework.bootspring-boot-starter-webtrueorg.springframework.cloudspring-cloud-starter-openfeigntrue

在提交订单时我们简单模拟需要获取商品的单价,所以在common-openfeign项目内我们要提供一个查询商品单价的服务接口,创建一个名为GoodClient的接口如下所示:

package org.minbox.chapter.common.openfeign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 商品服务接口定义
 *
 * @author 恒宇少年
 */
@FeignClient(name = "good-service")
@RequestMapping(value = "/good")
public interface GoodClient {
    /**
     * 获取商品价格
     *
     * @param goodId 商品编号
     * @return
     */
    @GetMapping(value = "/{goodId}")
    Double getGoodPrice(@PathVariable("goodId") Integer goodId);
}

注解解释:

  • @FeignClientSpringCloud Openfeign提供的接口客户端定义注解,通过value或者name来指定GoodClient访问的具体ServiceID,这里我们配置的value值为good-service项目spring.application.name配置参数ServiceID = spring.application.name)。
这样当我们通过注入GoodClient接口调用getGoodPrice方法时,底层通过OpenfeignHttp代理访问good-service的对应接口。

创建商品服务

下面我们再来创建一个名为good-serviceSpringBoot项目。

添加相关依赖

pom.xml项目配置文件内添加如下依赖:

org.minbox.frameworkapi-boot-starter-loggingorg.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-netflix-eureka-clientorg.minbox.chaptercommon-openfeign0.0.1-SNAPSHOT

可以看到我们在good-service项目依赖内添加了我们在上面创建的common-openfeign依赖模块,因为GoodClient服务接口的实现是在good-service项目内,我们需要添加common-openfeign依赖后创建对应的XxxController并实现GoodClient接口完成对应的业务逻辑实现。

商品业务实现

这里我们简单做个示例,将价格固定返回,实现GoodClient控制器如下所示:

package org.minbox.chapter.good.service;

import org.minbox.chapter.common.openfeign.GoodClient;
import org.springframework.web.bind.annotation.RestController;

/**
 * 商品服务接口实现
 *
 * @author 恒宇少年
 * @see GoodClient
 */
@RestController
public class GoodController implements GoodClient {
    @Override
    public Double getGoodPrice(Integer goodId) {
        if (goodId == 1) {
            return 15.6;
        }
        return 0D;
    }
}

注册到Eureka Server

我们需要将good-service注册到Eureka Server,修改application.yml配置文件如下所示:

# ServiceID
spring:
  application:
    name: good-service
# 端口号
server:
  port: 8082
# Eureka Config
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10000/eureka/
  instance:
    prefer-ip-address: true

配置上报的Logging Admin

我们需要将good-service的请求日志上报到Logging Admin,采用SpringCloud ServiceID的方式配置,修改application.yml配置文件如下所示:

api:
  boot:
    logging:
      # 控制台打印日志
      show-console-log: true
      # 美化打印日志
      format-console-log-json: true
      # 配置Logging Admin 服务编号
      discovery:
        service-id: logging-admin

启用Eureka Client & Logging

最后我们在XxxApplication入口类添加注解来启用Eureka Client以及Logging Client,如下所示:

/**
 * 商品服务
 *
 * @author 恒宇少年
 */
@SpringBootApplication
@EnableLoggingClient
@EnableDiscoveryClient
public class GoodServiceApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(GoodServiceApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(GoodServiceApplication.class, args);
        logger.info("{}服务启动成功.", "商品");
    }
}
至此我们的商品服务已经准备完成.

创建订单服务

创建一个名为order-serviceSpringBoot项目(建议参考源码,本章采用Maven多模块创建)。

添加相关依赖

修改pom.xml添加相关依赖如下所示:

org.minbox.frameworkapi-boot-starter-loggingorg.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-netflix-eureka-clientorg.springframework.cloudspring-cloud-starter-openfeignorg.minbox.chaptercommon-openfeign0.0.1-SNAPSHOT

订单业务实现

我们来模拟一个提交订单的场景,创建一个名为OrderController的控制器,如下所示:

/**
 * 订单控制器
 *
 * @author 恒宇少年
 */
@RestController
@RequestMapping(value = "/order")
public class OrderController {
    /**
     * 商品接口定义注入
     * {@link GoodClient}
     */
    @Autowired
    private GoodClient goodClient;

    @PostMapping
    public String submit(Integer goodId, Integer buyCount) {
        Double goodPrice = goodClient.getGoodPrice(goodId);
        Double orderAmount = goodPrice * buyCount;
        //...
        return "订单提交成功,订单总金额:" + orderAmount;
    }
}

注册到Eureka Server

将我们创建的order-service注册到Eureka Server,修改application.yml配置文件如下所示:

spring:
  application:
    name: order-service
server:
  port: 8081
# Eureka Config
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10000/eureka/
  instance:
    prefer-ip-address: true

配置上报的Logging Admin

我们需要将order-service的请求日志上报到Logging Admin,采用SpringCloud ServiceID的方式配置,修改application.yml配置文件如下所示:

api:
  boot:
    logging:
      # 控制台打印日志
      show-console-log: true
      # 美化打印日志
      format-console-log-json: true
      # 配置Logging Admin 服务编号
      discovery:
        service-id: logging-admin

启用Eureka Client & Logging

修改order-service入口类OrderServiceApplication,添加启用Eureka ClientLogging Client的注解,如下所示:

/**
 * 订单服务
 *
 * @author 恒宇少年
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableLoggingClient
@EnableFeignClients(basePackages = "org.minbox.chapter.common.openfeign")
public class OrderServiceApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(OrderServiceApplication.class);

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

注解解释:

  • @EnableFeignClients:该注解是Openfeign提供的启用自动扫描Client的配置,我们通过basePackages(基础包名)的方式进行配置扫描包下配置@FeignClient注解的接口,并为每个接口生成对应的代理实现并添加到Spring IOC容器。

    org.minbox.chapter.common.openfeign包名在common-openfeign项目内。

运行测试

依次启动项目,eureka-server > logging-admin > good-service > order-service

通过curl命令访问order-service内的提交订单地址:/order,如下所示:

➜ ~ curl -X POST http://localhost:8081/order/?goodId/=1/&buyCount/=3
订单提交成功,订单总金额:46.8
可以看到我们已经可以成功的获取订单的总金额,我们在/order请求方法内调用good-service获取商品的单价后计算得到订单总金额。

测试点:链路信息传递

我们通过控制台输出的日志信息来确认下链路信息(traceId、spanId)的透传是否正确。

收到order-service上报的日志

Receiving Service: 【order-service -> 127.0.0.1】, Request Log Report,Logging Content:[
    {
        "endTime":1573009439840,
        "httpStatus":200,
        "requestBody":"",
        "requestHeaders":{
            "host":"localhost:8081",
            "user-agent":"curl/7.64.1",
            "accept":"*/*"
        },
        "requestIp":"0:0:0:0:0:0:0:1",
        "requestMethod":"POST",
        "requestParam":"{/"buyCount/":/"3/",/"goodId/":/"1/"}",
        "requestUri":"/order",
        "responseBody":"订单提交成功,订单总金额:46.8",
        "responseHeaders":{},
        "serviceId":"order-service",
        "serviceIp":"127.0.0.1",
        "servicePort":"8081",
        "spanId":"241ef717-b0b3-4fcc-adae-b63ffd3dbbe4",
        "startTime":1573009439301,
        "timeConsuming":539,
        "traceId":"3e20cc72-c880-4575-90ed-d54a6b4fe555"
    }
]

收到good-service上报的日志

Receiving Service: 【good-service -> 127.0.0.1】, Request Log Report,Logging Content:[
    {
        "endTime":1573009439810,
        "httpStatus":200,
        "parentSpanId":"241ef717-b0b3-4fcc-adae-b63ffd3dbbe4",
        "requestBody":"",
        "requestHeaders":{
            "minbox-logging-x-parent-span-id":"241ef717-b0b3-4fcc-adae-b63ffd3dbbe4",
            "minbox-logging-x-trace-id":"3e20cc72-c880-4575-90ed-d54a6b4fe555",
            "host":"10.180.98.156:8082",
            "connection":"keep-alive",
            "accept":"*/*",
            "user-agent":"Java/1.8.0_211"
        },
        "requestIp":"10.180.98.156",
        "requestMethod":"GET",
        "requestParam":"{}",
        "requestUri":"/good/1",
        "responseBody":"15.6",
        "responseHeaders":{},
        "serviceId":"good-service",
        "serviceIp":"127.0.0.1",
        "servicePort":"8082",
        "spanId":"6339664e-097d-4a01-a734-935de52a7d44",
        "startTime":1573009439787,
        "timeConsuming":23,
        "traceId":"3e20cc72-c880-4575-90ed-d54a6b4fe555"
    }
]

结果分析:

  • 请求日志的入口为order-service所以并不存在parentSpanId(上级单元编号),而spanId(单元编号)、traceId(链路编号)也是新生成的。
  • 本次请求会经过good-service服务,因此parentSpanId则是order-service生成的spanIdtraceId同样也是order-service生成的,透传HttpHeader方式进行传递,表示在同一条请求链路上。

敲黑板,划重点

ApiBoot Logging支持使用Openfeign传递链路信息,内部通过Openfeign拦截器实现,源码详见:org.minbox.framework.logging.client.http.openfeign.LoggingOpenFeignInterceptor

traceId(链路编号)、parentSpanId(单元编号)通过HttpHeader的形式传递到目标访问服务,服务通过请求日志拦截器进行提取并设置链路绑定关系。

  • traceId传递时HttpHeader名称为:minbox-logging-x-trace-id.
  • parentSpanId传递时HttpHeader名称为:minbox-logging-x-parent-span-id
审核编辑 黄昊宇
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2964

    浏览量

    104688
  • spring
    +关注

    关注

    0

    文章

    340

    浏览量

    14334
  • MySQL
    +关注

    关注

    1

    文章

    804

    浏览量

    26519
  • 人脸识别
    +关注

    关注

    76

    文章

    4011

    浏览量

    81844
收藏 人收藏

    评论

    相关推荐

    EDAS再升级!全面支持Spring Cloud应用

    情况。除了微服务调用,EDAS还具备全的分布式跟踪功能,模拟最真实的用户场景,提前为系统创造可能面临的大促流量高峰场景。在吞吐能力和响应时间上,EDAS做了极大优化。在同等测试条件下与Spring
    发表于 02-02 15:20

    Dubbo Cloud Native 之路的实践与思考

    Native 基础设施服务发现(Service Discovery )如何选择EurekaConsulZookeeper负载均衡服务网关分布式配置服务熔断跟踪服务监控Cloud Native 架构选型
    发表于 07-05 16:05

    Spring Cloud Config公共配置解决方案

    Spring Cloud Config 多服务公共配置
    发表于 08-30 09:05

    使用Spring Cloud与Docker实战微服务

    使用Spring Cloud与Docker实战微服务
    发表于 09-09 08:31 7次下载
    使用<b class='flag-5'>Spring</b> <b class='flag-5'>Cloud</b>与Docker实战微服务

    ApiBoot Logging Admin可视化界面管理日志教程

    ApiBoot Logging Admin支持界面可视化查看请求日志信息,初期版本支持查看上报日志的服务列表、最新的日志等功能,还可以整
    的头像 发表于 12-10 22:03 495次阅读

    ApiBoot Logging使用Rest Template信息

    在上一篇文章【ApiBoot Logging使用SpringCloud Openfeign
    的头像 发表于 12-10 22:03 600次阅读

    ApiBoot Logging整合Spring Cloud Eureka负载均衡上报日志

    ApiBoot Logging支持整合服务注册中心(Eureka、Consul、Nacos Discovery、Zookeeper...)进行上报请求日志,Logging Client会从服务注...
    的头像 发表于 12-10 22:08 413次阅读

    ApiBoot Logging忽略路径不进行采集日志的教程

    ApiBoot Logging支持排除指定路径不参与日志的采集,当我们的服务集成actuator时,会不断的重复调用内置的路径导致大量采集到一些无关业...
    的头像 发表于 12-10 22:18 406次阅读

    修改ApiBoot Logging日志采集前缀的教程

    ApiBoot Logging支持指定单个或者多个路径的前缀进行采集,也就是我们可以指定/user/**或者/order/**下的单个或者同时指定多个路径进行...
    的头像 发表于 12-10 22:20 440次阅读

    Spring Cloud Function基于Spring Boot的函数计算框架

    ./oschina_soft/spring-cloud-function.zip
    发表于 05-13 10:16 0次下载
    <b class='flag-5'>Spring</b> <b class='flag-5'>Cloud</b> Function基于<b class='flag-5'>Spring</b> Boot的函数计算框架

    RabbitRpc基于spring cloud的微服务rpc调用

    ./oschina_soft/gitee-spring-cloud-rabbitrpc.zip
    发表于 06-14 09:51 1次下载
    RabbitRpc基于<b class='flag-5'>spring</b> <b class='flag-5'>cloud</b>的微服务rpc调用

    Spring Cloud Tencent发布最新匹配版本!

    无论北极星还是 Spring Cloud Tencent 当前都在积极的修复 Bug、完善用户体验、迭代新功能。所以 Spring Cloud Tencent 也第一时间适配了
    的头像 发表于 12-09 15:34 1093次阅读

    Spring Cloud 2022.0.0正式发布

    由于 Spring 现在提供了他们自己实现的接口 HTTP 客户端解决方案,因此从 2022.0.0 开始,Spring Cloud OpenFeign 已到达特性完成状态。这意味着
    的头像 发表于 12-22 10:39 718次阅读

    dubbo和spring cloud区别

    Dubbo和Spring Cloud是两个非常流行的微服务框架,各有自己的特点和优势。在本文中,我们将详细介绍Dubbo和Spring Cloud的区别。 1.架构设计: Dubbo是
    的头像 发表于 12-04 14:47 1668次阅读

    Spring Cloud Gateway网关框架

    Spring Cloud Gateway网关框架 本软件微服务架构中采用Spring Cloud Gateway网关控制框架,Spring
    的头像 发表于 08-22 09:58 477次阅读
    <b class='flag-5'>Spring</b> <b class='flag-5'>Cloud</b> Gateway网关框架