1、业务需求(记录用户行为日志)
在用户访问商品信息时,记录谁在什么时间,执行了什么操作,访问了什么方法,传递了什么参数,耗时是多少,最后的状态是成功还是失败,假如失败了,其具体错误信息是什么?
2、用户行为表的设计是怎样的?
CREATE TABLE `log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL COMMENT '用户名',
`operation` varchar(50) DEFAULT NULL COMMENT '用户操作',
`method` varchar(200) DEFAULT NULL COMMENT '请求方法',
`params` varchar(5000) DEFAULT NULL COMMENT '请求参数',
`time` bigint(20) NOT NULL COMMENT '执行时长(毫秒)',
`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',
`created_time` datetime DEFAULT NULL COMMENT '创建时间',
`status` int(11) DEFAULT '1',
`error` varchar(500) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8 COMMENT='用户日志';
3、具体的实现实现方案是怎样的?
1)基于AOP方式获取用户行为日志
2)封装用户行为日志并且写入到数据库
4、代码落地的具体方案是怎样的?
1)在数据库中添加日志表
2)创建一个日志对象用于封装用户日志信息(Log)
3)创建一个日志Mapper接口对象
4)创建一个日志Service接口及实现类对象
5)创建一个注解对象(@RequiredLog),用于描述需要记录日志的方法(切入点方法)
6)创建一个切面对象(LogAspect)
7)在切面中定义切入点表达式以及通知方法.(@Around)
6)在通知方法获取日志,封装日志,然后调用service方法记录日志到数据库
5、项目方案落地及运行过程有什么问题?
当用户访问量比较大时,发现系统响应速度有明显延迟,后续通过日志分析,底层记录
动作影响到了正常业务数据的响应速度.
6、如上问题的解决方案你是如何设计的?
将日志记录的操作,放到一个新的线程中去执行,最初的解决方案是自己创建一个
新的线程去执行,但是并发量比较大的时,不断创建和销毁线程会带来很大的资源消耗.
后续修改方案,调整为通过线程池中的线程去异步执行,例如在项目的启动类上添加
@EnableAsync注解启动异步任务配置,然后在需要异步执行的方法上添加@Async注解即可,
当然,我们也可以基于实际业务对池进行配置(可以在application.yml等配置文件中配置).
7、有没有更好的方案设计?
每个方案都是与具体业务相结合的,没有最好,只有更好.
当实际并发非常大时,即便是异步写日志,使用的是池中线程,但这些线程也有不够用的时候,
任务队列也满的时,所以面对这种情况,我可以将日志先写到消息队列,然后再异步落库