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...哈哈!!! 

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

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

  • 相关阅读:
    windwos8.1英文版安装SQL2008 R2中断停止的解决方案
    indwows8.1 英文版64位安装数据库时出现The ENU localization is not supported by this SQL Server media
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
    SQL数据附加问题
    eclipse,myeclipse中集合svn的方法
    JAVA SSH 框架介绍
    SSH框架-相关知识点
    SuperMapRealSpace Heading Tilt Roll的理解
    SuperMap iserver manage不能访问本地目的(IE9)
    Myeclipse中js文件中的乱码处理
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878604.html
Copyright © 2011-2022 走看看