ApiBoot Logging使用RestTemplate透傳鏈路信息

在上一篇文章【ApiBoot Logging使用SpringCloud Openfeign透傳鏈路信息】中咱們詳細的講解了ApiBoot Logging整合SpringCloud經過Openfeign進行透傳鏈路信息,包括traceId(鏈路編號)、parentSpanId(上級單元編號)等信息。 ApiBoot Logging不單單可使用Openfeign傳遞鏈路信息,還支持RestTemplate方式,本篇文章來詳細的講解下具體的使用方式。html

博客原文地址:blog.yuqiyu.com/apiboot-log…java

搭建Logging Admin

咱們須要搭建Logging Admin服務,用於接收業務服務上報的請求日誌信息,請參考【將ApiBoot Logging採集的日誌上報到Admin】文章內容.git

添加ApiBoot統一版本

因爲本章採用是Maven 多模塊的方式構建源碼,因此咱們只須要將ApiBoot統一版本的依賴配置在root項目的pom.xml內,以下所示:web

<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>
複製代碼

接下來咱們營造本篇文章的模擬場景查詢用戶基本信息時一併查詢出用戶的帳號餘額spring

建立帳戶服務

建立一個名爲account-serviceSpringBoot項目。json

添加相關依賴

在項目pom.xml配置文件內添加相關依賴,以下所示:api

<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地址,以下所示:bash

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類上添加以下所示:app

/** * 帳戶服務 * * @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,謝謝!!! 本篇文章示例源碼能夠經過如下途徑獲取,目錄爲SpringBoot2.x/apiboot-logging-using-resttemplate-transparent-traceid

做者我的 博客 使用開源框架 ApiBoot 助你成爲Api接口服務架構師

相關文章
相關標籤/搜索