通过 ApiBoot Logging
可以将每一条请求的详细信息获取到,在分布式部署方式中,一个请求可能会经过多个服务,如果是每个服务都 独立保存
请求日志信息,我们没有办法做到统一的控制,而且还会存在 日志数据库
与业务数据库
不一致的情况出现(可能会用到多数据源配置),正因为这个问题 ApiBoot Logging
提供了一个 Admin
的概念,将客户端采集到的的每一条日志都进行上报到 Admin
,由Admin
进行分析、保存等操作。
创建 Logging Admin 项目
ApiBoot Logging Admin
既然可以汇总每一个 业务服务
(ApiBoot Logging)的请求日志,因此我们需要将每一个 业务服务
采集单的日志进行上报到 Admin
,所以应该使用 独立的方式 进行部署,我们单独创建一个服务来专门采集请求日志然后进行保存。
初始化 Logging Admin 项目依赖
使用 idea
创建一个 SpringBoot
项目,pom.xml
配置文件内的依赖如下所示:
<dependencies>
<!--Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--ApiBoot Logging Admin-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-logging-admin</artifactId>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!--ApiBoot MyBatis Enhance-->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-starter-mybatis-enhance</artifactId>
</dependency>
</dependencies>
我们需要将采集到的请求日志进行保存到数据库,所以在项目内需要添加 数据库驱动
、 数据库连接池
相关的依赖,ApiBoot Logging Admin
内部通过 DataSource
进行操作数据,通过 ApiBoot MyBatis Enhance
的依赖可以自动化创建 DataSource
,摆脱手动创建并加入Spring IOC
容器。
添加 ApiBoot 统一版本依赖
<dependencyManagement>
<dependencies>
<!--ApiBoot 统一版本依赖 -->
<dependency>
<groupId>org.minbox.framework</groupId>
<artifactId>api-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
最新版的 ApiBoot,请访问:https://search.maven.org/sear…:api-boot-dependencies 进行查询。
启用 Logging Admin
添加 ApiBoot Logging Admin
依赖后还不能完全使用 Admin
的功能,我们需要通过 @EnableLoggingAdmin
注解来启用,该注解会自动将 Logging Admin
内所需要的部分类自动注册到Spring IOC
,在入口类添加注解如下所示:
/**
* ApiBoot Logging Admin 入口类
*/
@SpringBootApplication
@EnableLoggingAdmin
public class ApibootReportLogsByLoggingToAdminApplication {public static void main(String[] args) {SpringApplication.run(ApibootReportLogsByLoggingToAdminApplication.class, args);
}
}
配置日志数据源
application.yml
配置文件内数据源配置如下所示:
# 服务名称
spring:
application:
name: apiboot-report-logs-by-logging-to-admin
# 数据源相关配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
type: com.zaxxer.hikari.HikariDataSource
# 服务端口号
server:
port: 8081
控制台打印上报日志
ApiBoot Logging Admin
可以通过配置文件的方式进行控制是否在控制台打印采集到的请求日志信息,在 application.yml
配置文件内添加如下内容:
api:
boot:
logging:
# Logging Admin 相关配置
admin:
# 控制台显示采集的日志信息
show-console-report-log: true
注意:这里不要跟 ApiBoot Logging 所提供的
api.boot.logging.show-console-log
配置混淆。
美化控制台打印的上报日志
api:
boot:
logging:
# Logging Admin 相关配置
admin:
# 控制台输出时美化采集到的日志
format-console-log-json: true
注意:这里不要跟
api.boot.logging.format-console-log-json
配置混淆。
初始化日志表结构
ApiBoot Logging Admin
内部通过 固定的表结构 来进行存储 请求日志
、 服务信息
,建表语句如下所示:
SET NAMES utf8mb4 ;
--
-- Table structure for table `logging_request_logs`
--
CREATE TABLE `logging_request_logs` (`lrl_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键,UUID',
`lrl_service_detail_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '服务详情编号,关联 logging_service_details 主键',
`lrl_trace_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '链路 ID',
`lrl_parent_span_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上级跨度 ID',
`lrl_span_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '跨度 ID',
`lrl_start_time` mediumtext COLLATE utf8mb4_general_ci COMMENT '请求开始时间',
`lrl_end_time` mediumtext COLLATE utf8mb4_general_ci COMMENT '请求结束时间',
`lrl_http_status` int(11) DEFAULT NULL COMMENT '请求响应状态码',
`lrl_request_body` longtext COLLATE utf8mb4_general_ci COMMENT '请求主体内容',
`lrl_request_headers` text COLLATE utf8mb4_general_ci COMMENT '请求头信息',
`lrl_request_ip` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '发起请求客户端的 IP 地址',
`lrl_request_method` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求方式',
`lrl_request_uri` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求路径',
`lrl_response_body` longtext COLLATE utf8mb4_general_ci COMMENT '响应内容',
`lrl_response_headers` text COLLATE utf8mb4_general_ci COMMENT '响应头信息',
`lrl_time_consuming` int(11) DEFAULT NULL COMMENT '请求耗时',
`lrl_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '日志保存时间',
`lrl_request_params` text COLLATE utf8mb4_general_ci,
`lrl_exception_stack` text COLLATE utf8mb4_general_ci,
PRIMARY KEY (`lrl_id`),
KEY `logging_request_logs_LRL_SERVICE_DETAIL_ID_index` (`lrl_service_detail_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请求日志信息表';
--
-- Table structure for table `logging_service_details`
--
CREATE TABLE `logging_service_details` (`lsd_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL,
`lsd_service_id` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上报服务的 ID,对应 spring.application.name 配置值',
`lsd_service_ip` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上报服务的 IP 地址',
`lsd_service_port` int(11) DEFAULT NULL COMMENT '上报服务的端口号',
`lsd_last_report_time` timestamp NULL DEFAULT NULL COMMENT '最后一次上报时间,每次上报更新',
`lsd_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '首次上报时创建时间',
PRIMARY KEY (`lsd_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='上报日志的客户端服务详情';
ApiBoot Logging Admin
目前为止已经准备完毕,接下来我们需要修改 业务服务
将请求日志上报到Logging Admin
。
上报日志到指定 Logging Admin
我们将修改使用 ApiBoot Logging 进行统一管理请求日志文章源码,在 application.yml
添加 Logging Admin
的地址,如下所示:
api:
boot:
# ApiBoot Logging 日志组件配置
logging:
# 配置 Logging Admin 地址
admin:
server-address: 127.0.0.1:8081
api.boot.logging.admin-service-address
的配置格式为:Ip:Port
,我们只需要修改这一个地方即可,其他的工作都交付给 ApiBoot Logging
内部完成。
测试
我们将 ApiBoot Logging Admin
以及 业务服务
通过 Application
的形式进行启动。
使用 curl
访问测试地址如下所示:
~ curl http://localhost:8080/test\?name\=admin
你好:admin
我们查看 ApiBoot Logging Admin
控制台日志如下所示:
Receiving Service:【apiboot-unified-manage-request-logs -> 127.0.0.1】, Request Log Report,Logging Content:[
{
"endTime":1571641723779,
"httpStatus":200,
"requestBody":"","requestHeaders":{"server-region":"JiNan","host":"localhost:8080","user-agent":"curl/7.64.1","accept":"*/*"},"requestIp":"0:0:0:0:0:0:0:1","requestMethod":"GET","requestParam":"{\"name\":\"admin\"}","requestUri":"/test","responseBody":" 你好:admin","responseHeaders":{},"serviceId":"apiboot-unified-manage-request-logs","serviceIp":"127.0.0.1","servicePort":"8080","spanId":"95a73ca0-831b-45df-aa43-2b5887e8d98d","startTime":1571641723776,"timeConsuming":3,"traceId":"25a7de96-b3dd-48e5-9854-1a8069a4a681"}
]
我们已经看到了 Logging Admin
控制台打印的上报请求日志,而这条请求的日志是否已经被保存到数据库了还不确定,下面我使用命令行来查看数据库的日志信息。
查看 logging_service_details 表内数据
mysql> select * from logging_service_details\G;
*************************** 1. row ***************************
lsd_id: b069366a-25dc-41ec-8f09-242d81755cd0
lsd_service_id: apiboot-unified-manage-request-logs
lsd_service_ip: 10.180.98.112
lsd_service_port: 8080
lsd_last_report_time: 2019-10-21 02:14:26
lsd_create_time: 2019-10-21 15:14:26
logging_service_details
存放了每一个上报请求日志的 业务服务
基本信息,每一个服务基本信息会在 Logging Admin
内存中缓存一份,方便获取 service_id
进行存储日志,根据 ip
+port
+service_id
进行 确定唯一性,同一个服务只进行保存一次。
查看 logging_request_logs 表内数据
mysql> select * from logging_request_logs\G;
*************************** 1. row ***************************
lrl_id: c42761f6-b072-4744-8a17-d8e6097b85de
lrl_service_detail_id: b069366a-25dc-41ec-8f09-242d81755cd0
lrl_trace_id: 055329a0-cfc1-4606-baf0-4fb0cc905ba2
lrl_parent_span_id: NULL
lrl_span_id: aab83092-7749-4f88-8cb6-a949cc060197
lrl_start_time: 1571642065262
lrl_end_time: 1571642065286
lrl_http_status: 200
lrl_request_body:
lrl_request_headers: {"server-region":"JiNan","host":"localhost:8080","user-agent":"curl/7.64.1","accept":"*/*"}
lrl_request_ip: 0:0:0:0:0:0:0:1
lrl_request_method: GET
lrl_request_uri: /test
lrl_response_body: 你好:admin
lrl_response_headers: {}
lrl_time_consuming: 24
lrl_create_time: 2019-10-21 15:14:26
lrl_request_params: {"name":"admin"}
lrl_exception_stack: NULL
敲黑板画重点
本章我们进行集成了 ApiBoot Logging Admin
,将 业务服务
的每一次请求日志都进行上报到 Logging Admin
,通过数据库的方式进行保存请求日志,然后也可以通过其他的方式,而且可以通过spanId
以及 traceId
查看每一条请求链路的日志上下级关系以及每一个请求内耗时最多的span
,可以精准的进行优化服务性能。
作者个人 博客
使用开源框架 ApiBoot 助你成为 Api 接口服务架构师