zoukankan      html  css  js  c++  java
  • log4j 日志服务器_项目实际使用日记

    需求:近期有个项目要用到集群部署 + 话单日志,刚开始项目部署在多台linux服务器上,每台服务器上都生成自己的话单,但是对账系统只到一台服务器上取话单,这时就要把所有的话单日志放到同一台机子上;刚开始是通过linux地址映射到同一台机子上的,现在打算尝试用编码到项目里面实现这个需求。

            话单格式:订单号|价格|产品id

             注:生成的话单文件里面只能有“010101|5566|888999”等多行这样的信息,其他的信息不能放到话单里面来。

    暂时先熟悉下面资料

    http://blog.csdn.net/Didizyp/archive/2005/08/28/466730.aspx

    主要看:10.org.apache.log4j.net.SocketAppender,以套接字方式向服务器发送日志,然后由服务器将信息输出。

    下面的两个连接主要配置log4j服务器和客户端的配置

    http://jiangzhengjun.javaeye.com/blog/526364

    http://blog.csdn.net/z3h/archive/2005/11/01/520893.aspx

     一、 准备

      这里需要用到 Log4j、Quartz和java+Socket线程知识准备,下面是对应的入门连接

     http://blog.csdn.net/cuker919/category/640785.aspx     log4j的相关文章

    http://blog.csdn.net/cuker919/archive/2010/06/28/5698691.aspx   Quartz任务调度快速入门

    java+Socket线程:主要是Socket服务器和客户端知识,这里实现的是一个服务器多个客户端。

    二、改写log4j服务器的源代码

       这里改写的是SimpleSocketServer(服务器)和SocketNode(起一个线程监听客户端发过来的消息)。

    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InterruptedIOException;
    import java.io.ObjectInputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
    import org.apache.log4j.PropertyConfigurator;
    import org.apache.log4j.spi.LoggerRepository;
    import org.apache.log4j.spi.LoggingEvent;
    import org.apache.log4j.xml.DOMConfigurator;

    /** 
     * log4j服务器类,相当于SimpleSocketServer
     */ 
    public class SimpleSocketServerThread {
     private static Logger logger =  Logger.getLogger(SimpleSocketServerThread.class);
     public  int port;
     public  String configFile;
     ServerSocket serverSocket = null;
     static int count = 0;
     
     Socket socket;
     LoggerRepository hierarchy = LogManager.getLoggerRepository();
     ObjectInputStream ois;
     
     public SimpleSocketServerThread(){
     }
     
     public SimpleSocketServerThread(int port,String configFile){
      this.port = port;
      this.configFile = configFile;
         if(configFile.endsWith(".xml")) {
             DOMConfigurator.configure(configFile);
           } else {
             PropertyConfigurator.configure(configFile);
           }
        
         try {
        serverSocket = new ServerSocket(port);
        while(true){
         socket = serverSocket.accept();
         ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
         new ServerToLog4j(hierarchy,ois,socket);
        }
      } catch (IOException e) {
       logger.error(" ServerSocket IOException");
      } 
     }

     public static void main(String[] args) {
      SimpleSocketServerThread st = new SimpleSocketServerThread(9090,"E:/unipay_workspace/log4jService/WebRoot/WEB-INF/classes/socketserver.properties");
     }
    }

    /** 
     * 起一个线程监听客户端发过来的消息,并写进log4j ;本类改写了SocketNode类的源代码
     */ 
    class ServerToLog4j extends Thread{  
     private static Logger logger =  Logger.getLogger(ServerToLog4j.class);
        private LoggerRepository hierarchy;  
        ObjectInputStream ois;
        Socket socket;
        public ServerToLog4j(){
         
        }
       
        public ServerToLog4j(LoggerRepository hierarchy,ObjectInputStream ois,Socket socket){  
            this.hierarchy = hierarchy;  
            this.ois = ois;
            this.socket = socket;
            start();  
         }  
          
        public void run(){  
         LoggingEvent event;
            Logger remoteLogger;

            try {
              if (ois != null) {
                  while(true) {
                 // read an event from the wire
                 event = (LoggingEvent) ois.readObject();
                 // get a logger from the hierarchy. The name of the logger is taken to be the name contained in the event.
                 remoteLogger = hierarchy.getLogger(event.getLoggerName());
                 //event.logger = remoteLogger;
                 // apply the logger-level filter
                 if(event.getLevel().isGreaterOrEqual(remoteLogger.getEffectiveLevel())) {
                 // finally log the event as if was generated locally
                 remoteLogger.callAppenders(event);
               }
                }
              }
            } catch(java.io.EOFException e) {
             //读取的时候到达尾端抛出的异常,屏蔽掉
              //logger.error("Caught java.io.EOFException closing conneciton.");
            } catch(java.net.SocketException e) {
              logger.error("Caught java.net.SocketException closing conneciton.");
            } catch(InterruptedIOException e) {
              Thread.currentThread().interrupt();
              logger.error("Caught java.io.InterruptedIOException: ");
              logger.error("Closing connection.");
            } catch(IOException e) {
              logger.error("Caught java.io.IOException: ");
              logger.error("Closing connection.");
            } catch(Exception e) {
              logger.error("Unexpected exception. Closing conneciton.");
            } finally {
             if (ois != null) {
                    try {
                       ois.close();
                    } catch(Exception e) {
                       logger.error("ObjectInputStream Could not close connection.");
                    }
                 }
                 if (socket != null) {
                   try {
                     socket.close();
                   } catch(InterruptedIOException e) {
                       Thread.currentThread().interrupt();
                   } catch(IOException ex) {
                   }
                 }
            } 
        }  
    }

    三、配置log4j的服务器文件和客户端文件

    服务器文件名:socketserver.properties

    下面的log4j.MinuteRollingFileAppender是已经把log4j源码修改过了,原因是项目要求按15分钟分割一个话单,原来只能按1分钟分割,经过修改源码之后,可以按n分钟分割话单日志。

    MinuteRollingFileAppender实例请看:http://blog.csdn.net/cuker919/archive/2010/01/26/5257330.aspx

    log4j.rootLogger=WARN,C2,A3

    log4j.appender.A3=org.apache.log4j.RollingFileAppender
    log4j.appender.A3.file=e://home//a.txt
    log4j.appender.A3.MaxFileSize=1024KB
    log4j.appender.A3.MaxBackupIndex=999
    log4j.appender.A3.layout=org.apache.log4j.PatternLayout
    log4j.appender.A3.layout.ConversionPattern=/n/n[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

    #--------------------------------------------
    log4j.appender.C2=log4j.MinuteRollingFileAppender
    log4j.appender.C2.DatePattern='_'yyyyMMddHHmm00'.log'
    log4j.appender.C2.File=/home/vac2/test
    log4j.appender.C2.layout=org.apache.log4j.PatternLayout
    log4j.appender.C2.layout.ConversionPattern=/ %m%n
    log4j.logger.C2=WARN,C2

    客户端文件:log4j.properties(默认的log4j文件名)

    #soketClient
    log4j.rootCategory=,A1
    log4j.addivity.org.apache=true
    #
    log4j.appender.A1=org.apache.log4j.net.SocketAppender
    log4j.appender.A1.RemoteHost=127.0.0.1
    log4j.appender.A1.Port=9090
    log4j.appender.A1.LocationInfo=true

    客户端在web.xml文件里面的加载配置:

    <!--spring + log4j 加载 -->
     <context-param>
          <param-name>log4jConfigLocation</param-name>
          <param-value>/WEB-INF/classes/log4j.properties</param-value>
        </context-param>
     <context-param>
          <param-name>log4jRefreshInterval</param-name>
          <param-value>60000</param-value>
        </context-param>
     <listener>
          <listener-class>
            org.springframework.web.util.Log4jConfigListener
          </listener-class>
        </listener>

    四、Quartz的配置和相关的处理类

    在spring的配置文件里面applicationContext.xml加入Quartz的配置文件

    <!-- 定时任务 -->
        <import resource="classpath*:job.xml"></import>

    Quartz的配置文件job.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
      
        <bean id="logDealService" class="log4j.LogDealService">
         
        </bean>
        <!-- 下面是话单任务定时访问log4j,为了就是防止到达15(可配)分钟的时候,没有话单生成,强制每隔15分钟分割一个话单 -->
        <bean id="billJobDetail"
              class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" depends-on="logDealService"><!--依赖那个bean的装载-->
            <!--执行的bean-->
            <property name="targetObject" ref="logDealService"/>
            <!--执行的方法-->
            <property name="targetMethod" value="rollOver"/>
            <property name="concurrent" value="true"/>
        </bean>
        <bean id="cronTrigger"
              class="org.springframework.scheduling.quartz.CronTriggerBean" depends-on="billJobDetail">
            <property name="jobDetail" ref="billJobDetail"/>
            <property name="cronExpression">
                <!-- 每隔1min执行一次 -->
                <value>0/30 * * * * ?</value>
            </property>
        </bean>
       
        <!-- 下面是log4j 日志 SocketServer 服务任务,只加载一次-->
            <bean id="log4jServerJobDetail"
              class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" depends-on="logDealService"><!--依赖那个bean的装载-->
            <!--执行的bean-->
            <property name="targetObject" ref="logDealService"/>
            <!--执行的方法-->
            <property name="targetMethod" value="log4jServer"/>
            <property name="concurrent" value="true"/>
        </bean>
        <bean id="simpleTrigger"
              class="org.springframework.scheduling.quartz.SimpleTriggerBean" depends-on="log4jServerJobDetail">
            <property name="jobDetail" ref="log4jServerJobDetail"/>
            <property name="repeatCount">
                <!-- 只执行一次 -->
                <value>0</value>
            </property>
            <property name="repeatInterval">
             <!-- 重复执行间隔时间1微秒 -->
             <value>1</value>
            </property>
        </bean>
      
        <!-- 将上面的任务调度器进行管理 -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
            <property name="triggers">
                <list>
                    <ref bean="cronTrigger"/>
                    <ref bean="simpleTrigger" />
                </list>
            </property>
        </bean>
    </beans>

    Quartz任务的处理类:

    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
    import java.io.IOException;

    public class LogDealService {
        private Logger log2 = LogManager.getLogger(LogDealService.class);
       
       //打印话单日志文件
        private static Logger LOG = LogManager.getLogger("A1");
       
        /** 
         * 定时访问log4j的方法
         */
        public void rollOver() throws IOException {

             //为了客户端只打印话单所以要屏蔽掉一些不需要的日志,
            //这里可以根据你的项目需要配置更高的级别DEBUG, INFO, WARN, ERROR, FATAL
            LOG.warn("0000000000000"+" | "+"11111111111111111");
        }
       
        /** 
         * log4j日志服务器
         */
        public void log4jServer(){
         System.out.println("log4jServer quartz job startup .......");
         SimpleSocketServerThread st = new SimpleSocketServerThread(9090,"E:/unipay_workspace/log4jService/WebRoot/WEB-INF/classes/socketserver.properties");
        }
    }

    五、启动tomcat发现报错

         是log4j服务器ServerSocket和客户端socket报的错,不影响使用,其实如果把服务器和客户端分开打包,先启动服务器,客户端就不会报错,这里是把他们两都放到一个项目里面了,由于同时加载,服务器还没启动客户端就访问了,所以才报错。

    log4j:ERROR Could not connect to remote log4j server at [localhost]. We will try again later.
    java.net.ConnectException: Connection refused: connect
     at java.net.PlainSocketImpl.socketConnect(Native Method)
     at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
     at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:367)
     at java.net.Socket.connect(Socket.java:524)
     at java.net.Socket.connect(Socket.java:474)
     at java.net.Socket.<init>(Socket.java:371)
     at java.net.Socket.<init>(Socket.java:213)

    六、o(∩_∩)o...哈哈!!! 

          后面有时间再完善........

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Linux动态链接(4)ldd与ldconfig
    Linux动态链接(3)so文件映射地址
    Linux动态链接(2)so初始化执行
    Linux动态链接(1)惰性链接
    kill信号由谁接收处理
    gdb调试器之"测不准原则"
    gdb动态库延迟断点及线程/进程创建相关事件处理(下)
    gdb动态库延迟断点及线程/进程创建相关事件处理(上)
    Redis集群,备份,哨兵机制
    hyper-v虚拟机centos7网络配置
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878604.html
Copyright © 2011-2022 走看看