zoukankan      html  css  js  c++  java
  • 游戏上线后如何根据日志定位服务器问题

    在游戏服务器开发中,日志是定位服务器问题的一个主要手段。特别是游戏服务上线之后,大量的用户操作会产生庞大的日志数据,假如在线上的服务器出现了bug,或者是数据异常,那么怎么样在这么庞大的日志文件中,怎么样方便快速的找到自己所要的数据呢。

    线上的日志配置和开发环境的日志配置是不一样的。日志输出会分成几个级别,以log4j2为例,优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。

    • ALL 最低等级的,它会打印所有的日志输出。

    • TRACE 非常低等级的级别,一般记录的都是不重置的日志输出。

    • DEBUG 用于调试程序时的日志记录,它是最常用的级别之一。基本上程序中随处可见。但是如果程序调试没有问题之后,debug级别的日志是不应该再被记录的。

    • INFO 这个主要记录一些比较重要的数据。比如一些数据想要形成文件形式的存储,可以使用这个级别。在生产环境也是会记录这个级别的日志的。

    • WARN 这个级别会记录一些可以预料到,但是不影响程序运行的意外情况。比如如果某个值特别重置,如果没有配置的话,可以容忍使用默认值,服务器可以正常运行,但是需要给程序员知道这个问题,就使用这个日志级别记录。

    • ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。

    • FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

    • OFF 最高等级的,用于关闭所有日志记录。

    如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

    为了方便服务器上线之后查询日志,在开发的时候,就需要提前对日志进行良好的规划。在一些游戏服务器构架设计时,有些开发者为了统一记录日志,会在服务器中提供一个日志工具类,如下所示:

    public class LogUtil {
    
    	private static Logger logger = LoggerFactory.getLogger(LogUtil.class);
    	
    	public static void debug(String message) {
    		logger.debug(message);
    	}
    	public static void info(String message) {
    		logger.info(message);
    	}
    	public static void warn(String message) {
    		logger.warn(message);
    	}
    	public static void error(String message) {
    		logger.error(message);
    	}
    }
    
    

    然后在日志配置文件中添加一条配置,所有的日志都输出到同一个文件中。这样在开发的时候,需要打印日志的地方都统一调用这个日志工具类,以前我也这样使用过一段时间。这样做的好处就是在开发的时候不需要再创建使用日志类,直接调即可。统一打印到同一个日志文件中也省去了麻烦的配置。但是这就导到了别一个问题,也是我们今天要解决的问题,把所的日志都统一使用这一个日志工具类记录,如果上线之后,某个业务功能出问题了,想实时查看一下某个方法的调用时,打印的debug日志,该怎么办?如果将日志级别调到debug级别,那么所有的类的debug日志都将输出,产生的debug数据会比原来info级别多出好几倍来,如果这个时候在线人数比较多的话,就可以明显感觉到服务器的吞吐量下降,甚至出现数据返回延迟过高,客户端卡顿的现象。而且这个大量的debug日志输出,也不方便定位我们想要的debug日志数据。

    解决的办法也很简单,分而治之。在业务开发中,每个类的职责应该尽量的少,理想的状态就是一个类就处理一个问题或一类相同的问题。所以需要记录日志的类,应该使用自己单独的Logger。如下面代码所示:

    public class ChatDispatchHandler extends ChannelInboundHandlerAdapter {
    
    	private static Logger logger = LoggerFactory.getLogger(ChatDispatchHandler.class);
            //省略业务调
    }
    
    @Service
    public class UserService {
    	private static Logger logger = LoggerFactory.getLogger(UserService .class);
           //省略业务调
    }
    

    在开发阶段,想要所有的业务日志都输出为debug级别,以log4j2为例,配置如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 用于指定log4j自动重新配置的监测间隔时间,单位是秒 -->
    <configuration  monitorInterval="10">
    	<Properties>
    		<Property name="log-path">server_logs</Property>
    	</Properties>
    
    	<Appenders>
    		<Console name="console" target="SYSTEM_OUT">
    
    			<PatternLayout
    				pattern="%d{yyyy-MM-dd HH:mm:ss} %-5level %l - %msg%xEx%n" />
    		</Console>
    	</Appenders>
    	<Loggers>
    
    		<logger name="com.xinyue" level="debug" additivity="false">
    			<appender-ref ref="console" />
    		</logger>
    		
    
    		<root level="error">
    			<appender-ref ref="console" />
    		</root>
    	</Loggers>
    </configuration>
    

    这里使用到了一个日志logger配置规则,如果logger的name是一个包的目录,那么这个包下面包括子包的所有日志级别就是这个logger对应的级别。将来游戏服务器上线之后,就不需要debug级别的日志输出了,可以直接把它变成info级别,如下所示:

    <logger name="com.xinyue" level="info" additivity="false">
    	<appender-ref ref="console" />
    </logger>
    

    这样,这个包包括子包下面的所有日志输出都变成info级别了,debug记录的日志就不会输出了。
    那么如果线上的服务某个功能出现了问题,想要查看那个功能所在类的debug数据怎么做呢?这个问题日志框架的设计者已经想到了。在服务器运行的过程中,日志框架会定时自动扫描日志配置文件,如果发现日志配置文件有变动的话,它会自动热更新日志配置,对服务器运行没有任务的影响。以log4j2为例,在配置文件的最外层有这样一个配置,如下所示:

    <configuration  monitorInterval="10">
    
    

    它表示每隔10秒,检测一次配置文件是否变动,如果有变动,就会自动加载。利用这个特性,如果想查看某个类的debug输出,就可以在日志配置文件中添加这个类的logger配置,比如要查看ChatDispatchHandler这个类的debug输出,可以添加如下配置:

    <logger name="com.xinyue.chat.netty.ChatDispatchHandler" level="debug" additivity="false">
    	<appender-ref ref="console" />
    </logger>
    

    添加之后,过10秒就可以看到它的日志输出了。

  • 相关阅读:
    Xshell配置ssh免密码登录-密钥公钥(Public key)与私钥(Private Key)登录
    bypass disable_function的方法及蚁剑插件bypass-php-function使用
    cisco-GNS3-pix防火墙基本配置实操(持续更新)
    "锁定文件失败 打不开磁盘或它所依赖的某个快照磁盘。模块启动失败。未能启动虚拟机"--解决方法
    python实现图片转字符画
    GNS3--cisco路由器NAT配置
    python虚拟环境----virtualenv
    防火墙----思科路由器基本配置1
    XXE漏洞学习1
    vc程序设计-----位图
  • 原文地址:https://www.cnblogs.com/wgslucky/p/11833955.html
Copyright © 2011-2022 走看看