Socket(五)

news/2024/11/28 20:50:25/

文章目录

    • 1. 日志
    • 2. 如何记录日志

1. 日志

服务器要在无人看管的情况下运行很长时间,通常需要在很久以后对服务器中发生的情况进行调试,这很重要。由于这个原因,建议在存储服务器日志,至少要存储一段时间的日志。日志中通常希望记录的主要内容是:

  • 请求
  • 服务器错误

实际上,服务器一般会为这两项内容维护两个不同的日志,审计日志中,对应与服务器建立的每一个连接会分别包含一个记录,每个连接完成多个操作的服务器可能对每个操作都有一个记录。例如,dict服务器可能会为客户端查找的每个单词建立一个日志记录。错误日志则主要包含服务器运行期间发送的意外异常,主要记录程序中发生的一些异常。

2. 如何记录日志

在java1.4之前,程序基本使用的是第三方日志库,如log4j或Aache Commons Logging,之后官方提供了java.util.logging包,它能满足绝大多数需求。尽管可以根据需要来加载日志工具,不过需要最容易的办法是为每个类创建一个日志工具,如下:

private final static Logger auditLogger=Logger.getLogger("requests");

日志工具是线程安全的,所以将它们存储在共享静态字段中没有任何问题,实际上,往往需要这么做,因为即使不用在线程之间共享Logger对象,日志文件或数据块也需要共享。这在大量使用多线程的服务器中非常重要。上面的例子输出到一个名为"requests"的日志中,这个日志是什么、放在哪里取决于外部配置。它不一定是一个文件,可能是一个数据块、一个在多个服务器上运行的SOAP服务、同一个主机上运行的另一个java程序,或者是其它形式。一旦又了一个日志工具,可以使用多个方法写入这个日志。最基本的是log()。java.util.logging.Level中命名常量定义了七个级别,按严重性从高到低依次为:

  • Level.OFF
  • Level.SERVE
  • Level.WARNING
  • Level.INFO
  • Level.CONFIG
  • Level.FINE
  • Level.FINER
  • Level.FINEST
  • Level.ALL

我们通常会对审计日志使用INFO级别,对错误日志使用WARNING级别或SERVER级别。较低级别用于调试,不要在生成系统中使用。可以对各个日志使用任何方便的格式。一般来讲,每个记录应该包含一个时间戳、一个客户端地址,以及所处理的请求的任何特定信息。如果日志消息表示为一个叫错误,则要抛出特定的异常。Java会自动填入记录这个消息所在的代码位置,所以这个方面不用操心。

下面代码展示了如何为daytime服务器增加日志记录

public class QuizCardBuilder {private final static Logger auditLogger=Logger.getLogger("requests");private final static Logger errorLogger= Logger.getLogger("errors");public static void main(String[] args) {ExecutorService pool=Executors.newFixedThreadPool(50);try(ServerSocket server=new ServerSocket(8080)){while(true){try {Socket connection=server.accept();Callable<Void> task=new DaytimeTask(connection);pool.submit(task);}catch (IOException ex){errorLogger.log(Level.SEVERE,"accept  error"+ex);}catch (RuntimeException ex){errorLogger.log(Level.SEVERE,"unexcepted error"+ex.getMessage(),ex);}}}catch (IOException e) {errorLogger.log(Level.SEVERE,"Coundn`t start server"+e);}catch (RuntimeException e){errorLogger.log(Level.SEVERE,"Coundm`t start server"+e);}}private static class DaytimeTask implements Callable<Void>{private Socket connection;DaytimeTask(Socket connection){this.connection=connection;}@Overridepublic Void call() {try{Date now=new Date();//先写入日志记录以防万一客户端端口连接auditLogger.info(now+" "+connection.getRemoteSocketAddress());Writer out=new OutputStreamWriter(connection.getOutputStream());out.write(now.toString()+"\r\n");out.flush();}catch (IOException e){if(connection!=null){try {connection.close();} catch (IOException ex) {throw new RuntimeException(ex);}}}finally {if(connection!=null){try {connection.close();} catch (IOException ex) {throw new RuntimeException(ex);}}}return null;}}}

多次在终端使用Telnet与dayTime服务器通信

在这里插入图片描述

查看结果

在这里插入图片描述
上面的日志信息是直接在控制台打印的,如果我们希望将日志文件放到更加持久的位置,虽然我们可以在代码中指定,但是更好的是在配置文件中指定。这样就能改变日志位置而无需重新编译代码。java.util.logging.config.file系统属性采用常规的属性格式指向控制日志记录的一个文件。可以在启动虚拟机时加入vm配置-Djava.util.logging.config.file=_filename_参数来设置这个属性。

handlers=java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=/var/logs/daytime/requests.log
java.util.logging.FileHandler.limit=10000000
java.util.logging.FileHandler.count=2
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append=true
java.util.logging.FileHandler.format=%4$s: %5$s [%1$tc]%n

上面的配置指定来下面的内容:

  • 日志要写入文件
  • 请求日志应当在/var/logs/daytime/requests.log(INFO级别)
  • 错误日志应当在/var/logs/daytime/requests.log(SERVER级别)
  • 日志大小限制为10MB,然后轮换
  • 维护两个日志:当前日志和之前的日志
  • 使用基本文本格式化工具
  • 日志的每一行采用消息级别时间戳

http://www.ppmy.cn/news/105008.html

相关文章

mybatis中的一些使用

#{}与${}的区别 Delete("delete from emp where id #{id}") //生成预编译SQL语句&#xff0c;效率更高&#xff0c;将#{id}替换为“&#xff1f;”&#xff0c;也更安全&#xff0c;防止SQL注入&#xff0c;#不能出现在中&#xff0c;因此不能用于模糊查询 Delete(…

代码随想录算法训练营第五十六天 | 编辑距离2

583. 两个字符串的删除操作 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;动态规划之子序列&#xff0c;还是为了编辑距离做铺垫 | LeetCode&#xff1a;583.两个字符串的删除操作_哔哩哔哩_bilibili 状态&#xff1a;不会做。 思路 动态规划一 …

简单认识OSI(计算机网络分层)七层模型

前言 学校上课讲的太笼统啥也不是&#xff0c;自己学的太玄学似懂非懂突然在看到了一篇公众文文章。文章从初始到现在&#xff0c;步步为营的遇到一个解决一个前人的问题&#xff0c;有了细致入微的讲述&#xff0c;把之前学的死东西都连起来了。 如果让你来设计网络https://m…

java.awt.datatransfer.Clipboard剪切板获取String字符串文本

java.awt.datatransfer.Clipboard剪切板获取String字符串文本 有两种方法获取 直接从Clipboard获得 (String) systemClipboard.getData(DataFlavor.stringFlavor);从Clipboard获得Transable再获得String (String) systemClipboard.getContents(null).getTransferData(DataFlav…

效率至少提升数倍的office技巧

在现代办公室&#xff0c;WPS Office已成为无可替代的工具之一。然而&#xff0c;许多办公室员工却未能充分发掘WPS Office的强大功能和技巧。在快节奏的工作环境中&#xff0c;掌握一些WPS Office的技巧&#xff0c;将帮助员工们提高工作效率、改善文件处理和团队协作能力。下…

SpringCloudAlibaba下篇(GateWay,Skywalking)(超级无敌认真好用,万字收藏篇!!!!)

文章目录 SpringCloudAlibaba下篇(GateWay,Skywalking)1 GateWay1.1 什么是网关1.2 GateWay介绍1.3 GataWay的基本使用1.4 GataWay整合Nacos1.5 断言路由工厂1.5.1 内置断言路由工厂1.5.2 自定义断言路由工厂 1.6 过滤器工厂1.6.1 内置局部过滤器工厂1.6.2 自定义局部过滤器1.6…

基于Selenium+Python的web自动化测试框架

一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff1a;Firefo…