`

Log4j 集群环境下的 处理方案

    博客分类:
  • java
阅读更多

需求:近期有个项目要用到集群部署 + 话单日志,刚开始项目部署在多台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.iteye.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...哈哈!!! 

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

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cuker919/archive/2010/06/30/5704942.aspx

分享到:
评论

相关推荐

    Kafka+Log4j实现日志集中管理

    本主题将深入探讨如何使用Apache Kafka和Log4j来实现日志的集中管理和处理。Kafka是一个高吞吐量、分布式的消息发布订阅系统,而Log4j则是一款广泛使用的Java日志框架,二者结合能有效提升日志处理效率和分析能力。 ...

    数据库与log4jf的jar包

    数据库和Java日志框架log4j是开发Java应用程序时不可或缺的部分。在Java世界里,数据库连接和日志记录是两个核心功能,对于任何应用程序的稳定性和可维护性都至关重要。让我们详细了解一下这两个主题。 首先,...

    Tomcat集群部署方案

    在集群环境中,多个Tomcat实例协同工作,共同处理来自客户端的请求,从而实现负载均衡和故障转移。本方案将详细介绍如何通过Apache HTTP Server(简称Apache)和Tomcat的整合配置来创建一个简单的Tomcat集群。 首先...

    集群环境下hdfs jar包

    `log4j-1.2.17.jar`是日志框架Log4j,用于记录HDFS和Hadoop其他组件的运行日志,便于问题排查和系统监控。 最后,`commons-configuration-1.6.jar`是Apache Commons Configuration库,它提供了一种灵活的方式来管理...

    scribe+hadoop+log4j+hive+mysql

    综上所述,通过结合使用 Scribe、Hadoop、Log4j、Hive 和 MySQL 这些工具和技术,可以构建一套完整的日志数据采集、存储、处理和分析的解决方案。这对于深入理解用户行为、提升系统性能等方面都具有重要意义。

    基于Netty的Java WebSocket集群框架。.zip

    10. **监控与日志**:为了确保系统的稳定运行,通常需要集成监控系统(如Prometheus + Grafana)来监控服务器性能指标,同时使用日志框架(如Log4j或Logback)记录服务器运行日志,便于问题排查。 综上所述,"基于...

    11-Spring+Quartz定时任务最简集群版1

    3. `log4j-slf4j-impl`和`log4j-core`: 提供日志记录功能,使用Log4j与SLF4J适配器。 4. `spring-core`, `spring-context-support`, `spring-web`: 这些是Spring框架的核心组件,包括IoC容器、上下文支持以及Web相关...

    Mycat复制与高可用集群_herself36w_mycat_MYSQL_

    在实际环境中,搭建Mycat高可用集群需要经过一系列步骤,包括安装MySQL服务器、配置Mycat、编写配置文件、启动服务等。文件“Mycat复制与高可用集群.pptx”可能包含了详细的步骤和示例,对于理解并实践Mycat的复制与...

    Oracle9i安装OCS4J.properties问题解决

    logFileName = %s_ocs4jAdmin%\logs\ocs4j.log ``` 5. **重新尝试安装**:完成上述步骤后,重新启动Oracle9i的安装程序,并选择“Retry”选项以继续安装过程。 #### 四、注意事项 - 在编辑`OCS4J.properties`...

    redis-tomcat8以上集群所需要的jar :tomcat-redis-session-manager-master 等

    3. `slf4j-api.jar` 和 `slf4j-log4j12.jar`: Simple Logging Facade for Java (SLF4J) 是一个用于日志记录的API,`slf4j-log4j12.jar` 是SLF4J的一个实现,用于将日志信息输出到Log4j。 4. 可能还需要`log4j....

    eweb4j

    - **分布式应用**:考虑如何在集群环境中部署和管理eweb4j应用。 eweb4j作为一个全面的Web开发框架,为Java开发者提供了便捷的工具和结构,帮助他们构建高效、稳定且易于维护的Web应用。通过了解并掌握eweb4j的...

    Win7中使用Eclipse连接虚拟机中的Linux中的Hadoop2.5.0经验总结

    在Windows 7环境下,开发人员经常需要通过Eclipse IDE与远程Linux系统上的Hadoop集群进行交互,例如执行MapReduce任务。然而,由于操作系统和环境差异,可能会遇到一些问题。本文将详细阐述如何解决在Win7中使用...

    kafka跟storm收集日志解决方案

    1. **配置Log4j2**:在项目的`log4j2.xml`文件中,添加相应的Appender配置,指向Kafka的Topic。例如,对于`cms`模块,可以在配置文件中指定Topic为`cms`,并配置Kafka服务器地址等信息。 2. **设置日志级别**:根据...

    LSF集群使用命令说明

    LSF(Load Sharing Facility)是由IBM Platform Computing提供的高性能计算解决方案,旨在帮助用户管理和调度大量的并行任务。本文将基于提供的IBM Platform LSF Command Reference Version 8.3文档,对其中部分关键...

    ELK 7.16.1 最新一键安装铂金离线包

    本文将详细介绍ELK 7.16.1版本的关键知识点,特别是针对最新官方修复的log4j漏洞,以及如何进行一键离线安装。 **Elasticsearch** Elasticsearch是一款强大的分布式、全文搜索和分析引擎。在7.16.1版本中,它继续...

    高频大数据解决方案.pptx

    管理系统包括Nagios监控、Log4j日志记录、JMX接口和VoltDB企业版管理器,确保系统的稳定运行。 一个典型的 VoltDB 架构涵盖了从ERP到实时分析的各种业务场景,如CRM、订单管理、推荐系统、点击流分析、库存管理、...

Global site tag (gtag.js) - Google Analytics