文档章节

zookeeper实现log4j日志级别动调

 白中墨
发布于 2017/06/02 16:51
字数 756
阅读 69
收藏 1
  • 动态调整日志的目的和意义
  1. 灵活方便,对于线上遇到疑难问题需要排查时,可以灵活的对某台服务的日志做升降级,不需要重新发布
  2. 集中管理,通过日志管理组件,实现所有服务的日志级别统一控制
  • 实现方案总结

系统分为三部分组成,逻辑图如下:

  1. 日志监听组件
    1.1    业务系统注册至zookeeper
        @PostConstruct
        public void initLoggerZookeeper() {
            try {
                loggerContext = (LoggerContext) LogManager.getContext(false);
                tempZkPath = zkPath + getHostIp();
                initConnection();
                createNodeAddWatch();
               
            } catch (Exception e) {
                logger.error("init logger error: {}", e);
            }
      
        }
        @PreDestroy
        public void destroyZookeeperConn() {
            CloseableUtils.closeQuietly(node);
            CloseableUtils.closeQuietly(client);
        }
    
        /**
         * 
            * @MethodName: initLoggerConfig
            * @Description: 
            * @param 初始化zk连接
            * @return void
            * @throws
         */
        private void initConnection() {
            client = CuratorFrameworkFactory.newClient(zkConnectString, sessionTimeoutMs, connectionTimeoutMs,
                    new ExponentialBackoffRetry(1000, 3));
            client.getConnectionStateListenable().addListener(getConnectionStateListener());
            client.start();
            try {
                countDownLatch.await(3, TimeUnit.SECONDS);//不能因为zk注册影响核心业务,最长等待3秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 
            * @MethodName: getConnectionStateListener
            * @Description: 产生zookeeper的连接状态监听
            * @param @return
            * @return ConnectionStateListener
            * @throws
         */
        private ConnectionStateListener getConnectionStateListener() {
            ConnectionStateListener connListenner = new ConnectionStateListener() {
                @Override
                public void stateChanged(CuratorFramework client, ConnectionState newState) {
                    if (newState == ConnectionState.CONNECTED) {
                        countDownLatch.countDown();
                    }else if (newState == ConnectionState.LOST) {
                        CloseableUtils.closeQuietly(client);
                        countDownLatch = new CountDownLatch(1);
                        initLoggerZookeeper();
                    }else if(newState == ConnectionState.RECONNECTED) {
                        CloseableUtils.closeQuietly(client);
                        countDownLatch = new CountDownLatch(1);
                        initLoggerZookeeper();             
                    }
                }
            };
            return connListenner;
        }

    1.2    增加节点监听
        /**
         * 
            * @MethodName: createNodeAddWatch
            * @Description: 创建临时节点,增加节点监听
            * @param @throws Exception
            * @return void
            * @throws
         */
        private void createNodeAddWatch() throws Exception {
            Map<String, LoggerConfig> loggerMap = loggerContext.getConfiguration().getLoggers();
            LoggerConfig config = loggerMap.get("");
            String defaultLevel = "init";
            if(config != null) {
                Level level  = config.getLevel();
                defaultLevel = level.name();
            }
            node = new PersistentEphemeralNode(client, Mode.EPHEMERAL,
                    tempZkPath, defaultLevel.getBytes());
            node.start();
            node.waitForInitialCreate(2, TimeUnit.SECONDS);
            addWatcherForNode();
        }
        /**
         * 
            * @MethodName: addWatcherForNode
            * @Description: 增加watcher
            * @param @throws Exception
            * @return void
            * @throws
         */
        private void addWatcherForNode() throws Exception{
            client.getData().usingWatcher(getNodeWatcher()).inBackground().forPath(node.getActualPath());
        }
        /**
         * 
            * @MethodName: getNodeWatcher
            * @Description: 返回节点的监听器,监听数据变化
            * @param @param node
            * @param @return
            * @return Watcher
            * @throws
         */
        private Watcher getNodeWatcher() {
            Watcher watcher = new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if(event.getType() == EventType.NodeDataChanged) {
                        updateLogLevel();
                        try {
                            addWatcherForNode();
                        } catch (Exception e) {
                            logger.error("add watcher error: {}", e);
                        }
                    }
                }
            };
            return watcher;
        }

    1.3    根据节点内容变化,更新loggerContext
        /**
         * 
            * @MethodName: updateLogLevel
            * @Description: 更新日志等级
            * @param 
            * @return void
            * @throws
         */
        private void updateLogLevel() {
            String newLevel = null;
            try {
                newLevel = new String(client.getData().forPath(tempZkPath), "utf-8");
                logger.info("newLevel: {}", newLevel);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("nodeWatcher: ", e);
            }
            Map<String, LoggerConfig> loggerMap = loggerContext.getConfiguration().getLoggers();
            for(String loggerName : loggerMap.keySet() ) {
                LoggerConfig loggerConfig = loggerMap.get(loggerName);
                loggerConfig.setLevel(getMatchLevel(newLevel));
            }
            loggerContext.updateLoggers();
        }
        /**
         * 
            * @MethodName: getMatchLevel
            * @Description: 根据日志字符串获取Level,如果字符串匹配不到,则返回默认info等级
            * @param @param logLevel
            * @param @return
            * @return Level
            * @throws
         */
        private Level getMatchLevel(String logLevel) {
            Level matchLevel = Level.toLevel(logLevel, Level.INFO);
            return matchLevel;
        }
        /**
         * 
            * @MethodName: getHostIp
            * @Description: 获取服务的IP
            * @param @return
            * @param @throws Exception
            * @return String
            * @throws
         */
        private String getHostIp() throws Exception {
            InetAddress inetAddress = InetAddress.getLocalHost();
            return inetAddress.getHostAddress();
        }

     

  2. 日志管理平台
    核心代码如下:
      /**
         * 获取所有的日志服务列表
         */
        @Override
        public List<LogInfo> getLogList(String parentPath) {
            List<LogInfo> logInfoList = new ArrayList<>();
            try {
                List<String> machineList = client.getChildren().forPath(parentPath);
                for(String machine : machineList) {
                    logger.info(parentPath + "/" + machine);
                    String logLevel = new String(client.getData().forPath(parentPath + "/" + machine), "utf-8");
                    logger.info(logLevel);
                    LogInfo logInfo = new LogInfo();
                    logInfo.setIpAddress(machine);
                    logInfo.setLogLevel(logLevel);
                    logInfoList.add(logInfo);
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("getLogList error", e);
            }
            return logInfoList;
        }
        @PostConstruct
        public void initZKclient() {
            client = CuratorFrameworkFactory.newClient(zkConnectString, sessionTimeoutMs, connectionTimeoutMs,
                    new ExponentialBackoffRetry(1000, 3));
            client.start();
        }
        @PreDestroy
        public void destroyZookeeperConn() {
            CloseableUtils.closeQuietly(client);
        }
        
            /*
            * 
            * 
            * @param zkPath
            * @param level
            * @see com.xiaojukeji.ad.admin.service.interfaces.LogMachineService#updateLogLevel(java.lang.String, java.lang.String)
            */
        /**
         * 更新日志    
         */
        @Override
        public void updateLogLevel(String zkPath, String level, String hostName) {
            // TODO Auto-generated method stub
            try {
                System.out.println(zkPath + "/" + hostName);
                client.setData().forPath(zkPath + "/" + hostName, level.getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }

     

  3. zookeeper服务
    大名鼎鼎的分布式服务组件,这里就不做介绍了

 

© 著作权归作者所有

共有 人打赏支持
上一篇: classloader总结
下一篇: log4j2性能剖析
粉丝 0
博文 13
码字总数 18422
作品 0
昌平
私信 提问
MetaQ Log4j及服务器配置管理

一、使用Log4j扩展发送消息 Metaq还支持log4j发送消息,通过log4j写入的任何日志信息都将以消息的方式发送到Metaq的Broker服务器,只要通过简单的配置就可以。 如果要用到log4j扩展,你需要使...

一枚Sir
2015/11/03
0
0
Zookeeper集群部署和使用

Zookeeper 由 Apache Hadoop 的 Zookeeper 子项目发展而来,Google Chubby的一个开源实现。它是一个分布式应用程序协调服务,提供的功能包括:配置管理,名字服务,提供分布式同步、队列管理...

justin_peng
06/21
0
0
zkclient 2.1 发布,简单高效的zookeeper客户端

简单、高效的Zookeeper Java客户端。 让Zookeeper API 使用起来更简单 非常方便订阅各种事件并自动重新绑定事件(会话建立、节点修改、节点删除、子节点变更等) session过期自动重连、机制 ...

imxylz
2013/09/04
9.7K
0
kafka Failed to send messages after 3 tries.

我在网上搜了很多资料 说是zookeeper的问题,修改更改server.properties下的host.name,zookeeper.connect的localhost 为ip地址 怎么也不管用 后来就单独建了一个项目,发现没有问题。结论是j...

internetafei
2015/04/10
0
2
sqoop执行,不打印map日志,什么原因?

[root@zhujl conf]# sqoop import --connect jdbc:mysql://zhujl:3306/test --username 'root' --table student Warning: /usr/local/sqoop-1.4.5-cdh5.4.4/bin/../../hbase does not exist!......

君辰
2016/08/29
756
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊flink的FsStateBackend

序 本文主要研究一下flink的FsStateBackend StateBackend flink-runtime_2.11-1.7.0-sources.jar!/org/apache/flink/runtime/state/StateBackend.java @PublicEvolvingpublic interface Sta......

go4it
30分钟前
1
0
webpack配置proxyTable时pathRewrite无效的解决方法

webpack配置接口地址代理 在项目开发中,接口联调的时候一般都是同域名下,且不存在跨域的情况下进行接口联调,但是当我们在本地启动服务器后,比如本地开发服务下是 http://localhost:8080 ...

前端小攻略
31分钟前
1
0
安装jenkins

1.下载 wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.155/jenkins.war 2.后续操作和 dubbo 安装类似: (1)复制一份空白的tomcat,重命名为:jenkins-tomcat (2)war包放入t...

狼王黄师傅
39分钟前
2
0
zookeeper配置与使用

一.登录官网下载 不要带后缀的,那是公侧版本,下稳定版,比如3.4.9 二.安装与使用 解压后bin里是启动程序 配置文件:在conf下 复制zoo_sample.cfg改名为为zoo.cfg,打开zoo修改文件 临时数据保存...

小兵胖胖
今天
3
0
spring源码阅读笔记(一)

ClassPathXmlApplicationContext 与 FileSystemXmlApplicationContext 用了这么久的框架,是时候搞一下源码了,一般最初接触spring 从以下步骤开始 创建一个bean类 并创建 ooxx.xml之类的spr...

NotFound403
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部