设计一个中间件的访问日志组件

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 对任何一个系统,一个强大的日志记录功能是相当重要且必要的,根据日志的记录可以及时掌握系统运行时的健康状态及故障定位。然而作为web容器存在另外一种日志——访问日志。

对任何一个系统,一个强大的日志记录功能是相当重要且必要的,根据日志的记录可以及时掌握系统运行时的健康状态及故障定位。然而作为web容器存在另外一种日志——访问日志。访问日志一般会记录客户端的访问相关信息,包括客户端ip、请求时间、请求协议、请求方法、请求字节数、响应码、会话id、处理时间等等。通过访问日志可以统计访问用户的数量、访问时间分布等规律及个人爱好等等,而这些数据可以帮助公司在运营策略上做出抉择。


如果让你来设计一个访问日志组件你会如何来设计?你应该很快就会想到访问日志的核心功能就是将信息记录下来,至于要记录到哪里、以哪种形式来记录我们先不管,于是很快想到面向接口编程定义一个接口AccessLog,方法名就命名为log吧,需要传递参数包含请求对象和响应对象,如下,

public interface AccessLog {

 public void log(Request request, Response response);

}

定义一个好的接口是一个良好的开始,接下去要考虑的事是需要哪些类型的组件,针对前面的记录到哪里、以哪种形式记录我们最熟悉也最先想到的肯定就是以文件形式记录到磁盘里,于是我们来实现一个文件记录的访问日志组件吧。

public class FileAccessLog implements AccessLog{

public void log(Request request, Response response){

      String message=request与response中的值拼组成你需要的字符串。

try {

    Charset charset = Charset.defaultCharset();

    PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(

                    new FileOutputStream("c:/accesslog.log", true), charset), 128000),

                    false);

    writer.println(message);

    writer.flush();

 } catch (IOException e) {

}

}

}

看起来这是一个简单且不错的文件记录访问日志组件的实现,起码用于例子展示让人一看就觉得简单明了,采用PrintWriter对象用于写入操作,而且使用了BufferedWriter添加一个缓冲作用(使用Buffered如何能达到缓冲效果,如果你忘了请看我前面写的缓冲装置相关章节,看完一定会对缓冲有一个深入的了解),之所以把缓冲大小设置为128000是经验得出来的一个适合值,OutputStreamWriter则可以让字符进行编码,此处使用Charset工具提供的默认编码,FileOutputStream则指定写入的文件路径及文件名,而true表明追加日志而非覆盖。

假如你觉得用sql语言来统计日志的信息让你更加得心应手,那就写到文件就不符合需求,我们需要另外一个实现,通过jdbc将日志记录到数据库中。于是你必须另外建一个JDBCAccessLog类并重新实现log方法,使用JDBC操作数据库大家是最熟悉不过的了,受篇幅限制不详细写实现细节,但有一个前提是你必须跟数据库约好创建一张特定的表且表的结构要根据访问信息定义好。

public class JDBCAccessLog implements AccessLog{

public void log(Request request, Response response){

通过JDBCrequestresponse包含的访问信息组成一个sql语句插入数据库。

}

}

你还可以根据自己的需求定制各种各样的访问日志组件,只需实现AccessLog接口。但有时可能你会使用多个访问日志组件,例如又写入文件又持久化到数据库中,这时我们还是提供一个设配器给他吧,

public class AccessLogAdapter implements AccessLog {

    private AccessLog[] logs;

    public AccessLogAdapter(AccessLog log) {

        logs = new AccessLog[] { log };

    }

    public void add(AccessLog log) {

        AccessLog newArray[] = Arrays.copyOf(logs, logs.length + 1);

        newArray[newArray.length - 1] = log;

        logs = newArray;

    }

    public void log(Request request, Response response) {

        for (AccessLog log: logs) {

            log.log(request, response);

        }

    }

}

经过适配器的适配,log方法已经变成了遍历去调用多个访问日志组件的log方法,而适配器提供给对外的接口仍然是一个log方法,编写如下测试类log的调用将会分别向文件及数据库记录下hello tomcat

public class Test{

public static void main(String[] args){

AccessLog accessLog = new AccessLogAdapter(new FileAccessLog());

accessLog.add(new JDBCAccessLog()); 

accessLog.log(new Request("hello tomcat"),new Response());

}

}

经过以上的设计一个良好的访问日志组件就已经成型,而这也是Tomcat的访问日志组件的设计思路,而且Tomcat考虑到模块化和可配置扩展,它把访问日志组件作为一个管道中的一个阀门(管道机制忘了的朋友请看前面管道机制章节),这样就可以通过Tomcat的服务器配置文件配置实现访问日志记录功能,可以在任意容器中进行配置。


点击订购作者《Tomcat内核设计剖析》



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
消息中间件 存储 Java
RocketMQ(一):消息中间件缘起,一览整体架构及核心组件
【10月更文挑战第15天】本文介绍了消息中间件的基本概念和特点,重点解析了RocketMQ的整体架构和核心组件。消息中间件如RocketMQ、RabbitMQ、Kafka等,具备异步通信、持久化、削峰填谷、系统解耦等特点,适用于分布式系统。RocketMQ的架构包括NameServer、Broker、Producer、Consumer等组件,通过这些组件实现消息的生产、存储和消费。文章还提供了Spring Boot快速上手RocketMQ的示例代码,帮助读者快速入门。
|
6月前
|
Perl
CocoaLumberjack增强异步日志组件BITCocoaLumberjack的使用
CocoaLumberjack增强异步日志组件BITCocoaLumberjack的使用
61 1
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
49 2
|
1月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
59 0
|
3月前
|
Ubuntu Linux 测试技术
在Linux中,已知 apache 服务的访问日志按天记录在服务器本地目录/app/logs 下,由于磁盘空间紧张现在要求只能保留最近7天的访问日志,请问如何解决?
在Linux中,已知 apache 服务的访问日志按天记录在服务器本地目录/app/logs 下,由于磁盘空间紧张现在要求只能保留最近7天的访问日志,请问如何解决?
|
3月前
|
应用服务中间件 Linux nginx
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
|
3月前
|
消息中间件 监控 搜索推荐
OpenFeign日志组件Logger原理与应用
该文章详细解释了如何在OpenFeign中配置并使用请求和响应的GZIP压缩功能。
|
4月前
|
存储 开发框架 前端开发
循序渐进VUE+Element 前端应用开发(31)--- 系统的日志管理,包括登录日志、接口访问日志、实体变化历史日志
循序渐进VUE+Element 前端应用开发(31)--- 系统的日志管理,包括登录日志、接口访问日志、实体变化历史日志
|
3月前
|
网络安全
【Azure Service Bus】启用诊断日志来获取客户端访问Azure Service Bus的IP地址 [2024-03-26 实验结果失败]
【Azure Service Bus】启用诊断日志来获取客户端访问Azure Service Bus的IP地址 [2024-03-26 实验结果失败]
|
3月前
|
Kubernetes API Docker
在K8S中,如何查看kubelet组件的日志?
在K8S中,如何查看kubelet组件的日志?
下一篇
无影云桌面