ApiBoot Logging可以無縫整合SpringCloud來采集請求日志,目前支持RestTemplate、Openfeign兩種方式,我們本章來講解下在使用Openfeign完成服務(wù)之間請求相互調(diào)用的一條鏈路請求日志是否可以都采集到。
搭建Eureka Server
我們先來搭建一個Eureka Server,請訪問【搭建服務(wù)注冊中心Eureka Server】文章內(nèi)容查看具體搭建流程。
搭建Logging Admin
我們需要搭建一個Logging Admin用于接收Logging Client上報的請求日志,請訪問【ApiBoot Logging整合SpringCloud Eureka負(fù)載均衡上報日志】查看具體的搭建流程。
我們本章來模擬提交訂單的業(yè)務(wù)邏輯,涉及到兩個服務(wù),分別是:商品服務(wù)、訂單服務(wù),接下來我們需要來創(chuàng)建這兩個服務(wù)。
添加ApiBoot & SpringCloud統(tǒng)一版本
由于是采用Maven 多模塊項(xiàng)目,存在繼承關(guān)系,我們只需要在root模塊添加版本依賴即可,其他子模塊就可以直接使用,如下所示:
1.82.1.5.RELEASEGreenwich.SR3org.minbox.frameworkapi-boot-dependencies${api.boot.version}pomimportorg.springframework.cloudspring-cloud-dependencies${spring.cloud.version}pomimport
創(chuàng)建公共Openfeign接口定義
學(xué)習(xí)過Openfeign的同學(xué)應(yīng)該都知道,Openfeign可以繼承實(shí)現(xiàn),我們只需要創(chuàng)建一個公共的服務(wù)接口定義,在實(shí)現(xiàn)該接口的服務(wù)進(jìn)行業(yè)務(wù)實(shí)現(xiàn),在調(diào)用該接口的地方直接注入即可。
下面我們創(chuàng)建一個名為common-openfeign的公共依賴項(xiàng)目,pom.xml添加依賴如下所示:
org.springframework.bootspring-boot-starter-webtrueorg.springframework.cloudspring-cloud-starter-openfeigntrue
在提交訂單時我們簡單模擬需要獲取商品的單價,所以在common-openfeign項(xiàng)目內(nèi)我們要提供一個查詢商品單價的服務(wù)接口,創(chuàng)建一個名為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;
/**
* 商品服務(wù)接口定義
*
* @author 恒宇少年
*/
@FeignClient(name = "good-service")
@RequestMapping(value = "/good")
public interface GoodClient {
/**
* 獲取商品價格
*
* @param goodId 商品編號
* @return
*/
@GetMapping(value = "/{goodId}")
Double getGoodPrice(@PathVariable("goodId") Integer goodId);
}
注解解釋:
-
@FeignClient:SpringCloud Openfeign提供的接口客戶端定義注解,通過value或者name來指定GoodClient訪問的具體ServiceID,這里我們配置的value值為good-service項(xiàng)目spring.application.name配置參數(shù)(ServiceID=spring.application.name)。
這樣當(dāng)我們通過注入GoodClient接口調(diào)用getGoodPrice方法時,底層通過Openfeign的Http代理訪問good-service的對應(yīng)接口。
創(chuàng)建商品服務(wù)
下面我們再來創(chuàng)建一個名為good-service的SpringBoot項(xiàng)目。
添加相關(guān)依賴
在pom.xml項(xiàng)目配置文件內(nèi)添加如下依賴:
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項(xiàng)目依賴內(nèi)添加了我們在上面創(chuàng)建的common-openfeign依賴模塊,因?yàn)?code>GoodClient服務(wù)接口的實(shí)現(xiàn)是在good-service項(xiàng)目內(nèi),我們需要添加common-openfeign依賴后創(chuàng)建對應(yīng)的XxxController并實(shí)現(xiàn)GoodClient接口完成對應(yīng)的業(yè)務(wù)邏輯實(shí)現(xiàn)。
商品業(yè)務(wù)實(shí)現(xiàn)
這里我們簡單做個示例,將價格固定返回,實(shí)現(xiàn)GoodClient的控制器如下所示:
package org.minbox.chapter.good.service;
import org.minbox.chapter.common.openfeign.GoodClient;
import org.springframework.web.bind.annotation.RestController;
/**
* 商品服務(wù)接口實(shí)現(xiàn)
*
* @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 服務(wù)編號
discovery:
service-id: logging-admin
啟用Eureka Client & Logging
最后我們在XxxApplication入口類添加注解來啟用Eureka Client以及Logging Client,如下所示:
/**
* 商品服務(wù)
*
* @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("{}服務(wù)啟動成功.", "商品");
}
}
至此我們的商品服務(wù)已經(jīng)準(zhǔn)備完成.
創(chuàng)建訂單服務(wù)
創(chuàng)建一個名為order-service的SpringBoot項(xiàng)目(建議參考源碼,本章采用Maven多模塊創(chuàng)建)。
添加相關(guān)依賴
修改pom.xml添加相關(guān)依賴如下所示:
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
訂單業(yè)務(wù)實(shí)現(xiàn)
我們來模擬一個提交訂單的場景,創(chuàng)建一個名為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
將我們創(chuàng)建的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 服務(wù)編號
discovery:
service-id: logging-admin
啟用Eureka Client & Logging
修改order-service入口類OrderServiceApplication,添加啟用Eureka Client、Logging Client的注解,如下所示:
/**
* 訂單服務(wù)
*
* @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("{}服務(wù)啟動成功.", "");
}
}
注解解釋:
-
@EnableFeignClients:該注解是Openfeign提供的啟用自動掃描Client的配置,我們通過basePackages(基礎(chǔ)包名)的方式進(jìn)行配置掃描包下配置@FeignClient注解的接口,并為每個接口生成對應(yīng)的代理實(shí)現(xiàn)并添加到Spring IOC容器。org.minbox.chapter.common.openfeign包名在common-openfeign項(xiàng)目內(nèi)。
運(yùn)行測試
依次啟動項(xiàng)目,eureka-server > logging-admin > good-service > order-service。
通過curl命令訪問order-service內(nèi)的提交訂單地址:/order,如下所示:
? ~ curl -X POST http://localhost:8081/order/?goodId/=1/&buyCount/=3
訂單提交成功,訂單總金額:46.8
可以看到我們已經(jīng)可以成功的獲取訂單的總金額,我們在/order請求方法內(nèi)調(diào)用good-service獲取商品的單價后計算得到訂單總金額。
測試點(diǎn):鏈路信息傳遞
我們通過控制臺輸出的日志信息來確認(rèn)下鏈路信息(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"
}
]
結(jié)果分析:
-
請求日志的入口為
order-service所以并不存在parentSpanId(上級單元編號),而spanId(單元編號)、traceId(鏈路編號)也是新生成的。 -
本次請求會經(jīng)過
good-service服務(wù),因此parentSpanId則是order-service生成的spanId,traceId同樣也是order-service生成的,透傳HttpHeader方式進(jìn)行傳遞,表示在同一條請求鏈路上。
敲黑板,劃重點(diǎn)
ApiBoot Logging支持使用Openfeign傳遞鏈路信息,內(nèi)部通過Openfeign攔截器實(shí)現(xiàn),源碼詳見:org.minbox.framework.logging.client.http.openfeign.LoggingOpenFeignInterceptor。
將traceId(鏈路編號)、parentSpanId(單元編號)通過HttpHeader的形式傳遞到目標(biāo)訪問服務(wù),服務(wù)通過請求日志攔截器進(jìn)行提取并設(shè)置鏈路綁定關(guān)系。
-
traceId傳遞時HttpHeader名稱為:minbox-logging-x-trace-id. -
parentSpanId傳遞時HttpHeader名稱為:minbox-logging-x-parent-span-id
審核編輯 黃昊宇 -
JAVA
+關(guān)注
關(guān)注
20文章
3001瀏覽量
116456 -
spring
+關(guān)注
關(guān)注
0文章
341瀏覽量
15940 -
MySQL
+關(guān)注
關(guān)注
1文章
906瀏覽量
29554 -
人臉識別
+關(guān)注
關(guān)注
77文章
4127瀏覽量
88503
發(fā)布評論請先 登錄
EDAS再升級!全面支持Spring Cloud應(yīng)用
Dubbo Cloud Native 之路的實(shí)踐與思考
使用Spring Cloud與Docker實(shí)戰(zhàn)微服務(wù)
ApiBoot Logging Admin可視化界面管理日志教程
ApiBoot Logging使用Rest Template透傳鏈路信息
ApiBoot Logging整合Spring Cloud Eureka負(fù)載均衡上報日志
ApiBoot Logging忽略路徑不進(jìn)行采集日志的教程
修改ApiBoot Logging日志采集前綴的教程
Spring Cloud Function基于Spring Boot的函數(shù)計算框架
RabbitRpc基于spring cloud的微服務(wù)rpc調(diào)用
Spring Cloud Tencent發(fā)布最新匹配版本!
Spring Cloud 2022.0.0正式發(fā)布
dubbo和spring cloud區(qū)別
Spring Cloud Gateway網(wǎng)關(guān)框架
ApiBoot Logging使用Spring Cloud Openfeign透傳鏈路信息
評論