ApiBoot Logging可以無(wú)縫整合SpringCloud來(lái)采集請(qǐng)求日志,目前支持RestTemplate、Openfeign兩種方式,我們本章來(lái)講解下在使用Openfeign完成服務(wù)之間請(qǐng)求相互調(diào)用的一條鏈路請(qǐng)求日志是否可以都采集到。
搭建Eureka Server
我們先來(lái)搭建一個(gè)Eureka Server,請(qǐng)?jiān)L問(wèn)【搭建服務(wù)注冊(cè)中心Eureka Server】文章內(nèi)容查看具體搭建流程。
搭建Logging Admin
我們需要搭建一個(gè)Logging Admin用于接收Logging Client上報(bào)的請(qǐng)求日志,請(qǐng)?jiān)L問(wèn)【ApiBoot Logging整合SpringCloud Eureka負(fù)載均衡上報(bào)日志】查看具體的搭建流程。
我們本章來(lái)模擬提交訂單的業(yè)務(wù)邏輯,涉及到兩個(gè)服務(wù),分別是:商品服務(wù)、訂單服務(wù),接下來(lái)我們需要來(lái)創(chuàng)建這兩個(gè)服務(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í)過(guò)Openfeign的同學(xué)應(yīng)該都知道,Openfeign可以繼承實(shí)現(xiàn),我們只需要?jiǎng)?chuàng)建一個(gè)公共的服務(wù)接口定義,在實(shí)現(xiàn)該接口的服務(wù)進(jìn)行業(yè)務(wù)實(shí)現(xiàn),在調(diào)用該接口的地方直接注入即可。
下面我們創(chuàng)建一個(gè)名為common-openfeign的公共依賴項(xiàng)目,pom.xml添加依賴如下所示:
org.springframework.bootspring-boot-starter-webtrueorg.springframework.cloudspring-cloud-starter-openfeigntrue
在提交訂單時(shí)我們簡(jiǎn)單模擬需要獲取商品的單價(jià),所以在common-openfeign項(xiàng)目?jī)?nèi)我們要提供一個(gè)查詢商品單價(jià)的服務(wù)接口,創(chuàng)建一個(gè)名為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 {
/**
* 獲取商品價(jià)格
*
* @param goodId 商品編號(hào)
* @return
*/
@GetMapping(value = "/{goodId}")
Double getGoodPrice(@PathVariable("goodId") Integer goodId);
}
注解解釋:
-
@FeignClient:SpringCloud Openfeign提供的接口客戶端定義注解,通過(guò)value或者name來(lái)指定GoodClient訪問(wèn)的具體ServiceID,這里我們配置的value值為good-service項(xiàng)目spring.application.name配置參數(shù)(ServiceID=spring.application.name)。
這樣當(dāng)我們通過(guò)注入GoodClient接口調(diào)用getGoodPrice方法時(shí),底層通過(guò)Openfeign的Http代理訪問(wèn)good-service的對(duì)應(yīng)接口。
創(chuàng)建商品服務(wù)
下面我們?cè)賮?lái)創(chuàng)建一個(gè)名為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
可以看到我們?cè)?code>good-service項(xiàng)目依賴內(nèi)添加了我們?cè)谏厦鎰?chuàng)建的common-openfeign依賴模塊,因?yàn)?code>GoodClient服務(wù)接口的實(shí)現(xiàn)是在good-service項(xiàng)目?jī)?nèi),我們需要添加common-openfeign依賴后創(chuàng)建對(duì)應(yīng)的XxxController并實(shí)現(xiàn)GoodClient接口完成對(duì)應(yīng)的業(yè)務(wù)邏輯實(shí)現(xiàn)。
商品業(yè)務(wù)實(shí)現(xiàn)
這里我們簡(jiǎn)單做個(gè)示例,將價(jià)格固定返回,實(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;
}
}
注冊(cè)到Eureka Server
我們需要將good-service注冊(cè)到Eureka Server,修改application.yml配置文件如下所示:
# ServiceID
spring:
application:
name: good-service
# 端口號(hào)
server:
port: 8082
# Eureka Config
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10000/eureka/
instance:
prefer-ip-address: true
配置上報(bào)的Logging Admin
我們需要將good-service的請(qǐng)求日志上報(bào)到Logging Admin,采用SpringCloud ServiceID的方式配置,修改application.yml配置文件如下所示:
api:
boot:
logging:
# 控制臺(tái)打印日志
show-console-log: true
# 美化打印日志
format-console-log-json: true
# 配置Logging Admin 服務(wù)編號(hào)
discovery:
service-id: logging-admin
啟用Eureka Client & Logging
最后我們?cè)?code>XxxApplication入口類添加注解來(lái)啟用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ù)啟動(dòng)成功.", "商品");
}
}
至此我們的商品服務(wù)已經(jīng)準(zhǔn)備完成.
創(chuàng)建訂單服務(wù)
創(chuàng)建一個(gè)名為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)
我們來(lái)模擬一個(gè)提交訂單的場(chǎng)景,創(chuàng)建一個(gè)名為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;
}
}
注冊(cè)到Eureka Server
將我們創(chuàng)建的order-service注冊(cè)到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
配置上報(bào)的Logging Admin
我們需要將order-service的請(qǐng)求日志上報(bào)到Logging Admin,采用SpringCloud ServiceID的方式配置,修改application.yml配置文件如下所示:
api:
boot:
logging:
# 控制臺(tái)打印日志
show-console-log: true
# 美化打印日志
format-console-log-json: true
# 配置Logging Admin 服務(wù)編號(hào)
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ù)啟動(dòng)成功.", "");
}
}
注解解釋:
-
@EnableFeignClients:該注解是Openfeign提供的啟用自動(dòng)掃描Client的配置,我們通過(guò)basePackages(基礎(chǔ)包名)的方式進(jìn)行配置掃描包下配置@FeignClient注解的接口,并為每個(gè)接口生成對(duì)應(yīng)的代理實(shí)現(xiàn)并添加到Spring IOC容器。org.minbox.chapter.common.openfeign包名在common-openfeign項(xiàng)目?jī)?nèi)。
運(yùn)行測(cè)試
依次啟動(dòng)項(xiàng)目,eureka-server > logging-admin > good-service > order-service。
通過(guò)curl命令訪問(wèn)order-service內(nèi)的提交訂單地址:/order,如下所示:
? ~ curl -X POST http://localhost:8081/order/?goodId/=1/&buyCount/=3
訂單提交成功,訂單總金額:46.8
可以看到我們已經(jīng)可以成功的獲取訂單的總金額,我們?cè)?code>/order請(qǐng)求方法內(nèi)調(diào)用good-service獲取商品的單價(jià)后計(jì)算得到訂單總金額。
測(cè)試點(diǎn):鏈路信息傳遞
我們通過(guò)控制臺(tái)輸出的日志信息來(lái)確認(rèn)下鏈路信息(traceId、spanId)的透?jìng)魇欠裾_。
收到order-service上報(bào)的日志
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上報(bào)的日志
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é)果分析:
-
請(qǐng)求日志的入口為
order-service所以并不存在parentSpanId(上級(jí)單元編號(hào)),而spanId(單元編號(hào))、traceId(鏈路編號(hào))也是新生成的。 -
本次請(qǐng)求會(huì)經(jīng)過(guò)
good-service服務(wù),因此parentSpanId則是order-service生成的spanId,traceId同樣也是order-service生成的,透?jìng)鱄ttpHeader方式進(jìn)行傳遞,表示在同一條請(qǐng)求鏈路上。
敲黑板,劃重點(diǎn)
ApiBoot Logging支持使用Openfeign傳遞鏈路信息,內(nèi)部通過(guò)Openfeign攔截器實(shí)現(xiàn),源碼詳見(jiàn):org.minbox.framework.logging.client.http.openfeign.LoggingOpenFeignInterceptor。
將traceId(鏈路編號(hào))、parentSpanId(單元編號(hào))通過(guò)HttpHeader的形式傳遞到目標(biāo)訪問(wèn)服務(wù),服務(wù)通過(guò)請(qǐng)求日志攔截器進(jìn)行提取并設(shè)置鏈路綁定關(guān)系。
-
traceId傳遞時(shí)HttpHeader名稱為:minbox-logging-x-trace-id. -
parentSpanId傳遞時(shí)HttpHeader名稱為:minbox-logging-x-parent-span-id
審核編輯 黃昊宇 -
JAVA
+關(guān)注
關(guān)注
20文章
3001瀏覽量
116439 -
spring
+關(guān)注
關(guān)注
0文章
341瀏覽量
15940 -
MySQL
+關(guān)注
關(guān)注
1文章
906瀏覽量
29535 -
人臉識(shí)別
+關(guān)注
關(guān)注
77文章
4127瀏覽量
88472
發(fā)布評(píng)論請(qǐng)先 登錄
EDAS再升級(jí)!全面支持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ù)載均衡上報(bào)日志
ApiBoot Logging忽略路徑不進(jìn)行采集日志的教程
修改ApiBoot Logging日志采集前綴的教程
Spring Cloud Function基于Spring Boot的函數(shù)計(jì)算框架
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透?jìng)麈溌沸畔?/h1>
評(píng)論