文档章节

zookeeper实现log4j日志级别动调

 白中墨
发布于 2017/06/02 16:51
字数 756
阅读 40
收藏 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服务
    大名鼎鼎的分布式服务组件,这里就不做介绍了

 

© 著作权归作者所有

共有 人打赏支持
粉丝 0
博文 13
码字总数 18422
作品 0
昌平
Zookeeper集群部署和使用

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

justin_peng
06/21
0
0
MetaQ Log4j及服务器配置管理

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

一枚Sir
2015/11/03
0
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
使用ZooKeeper提供的Java API操作ZooKeeper

建立客户端与zk服务端的连接 我们先来创建一个普通的maven工程,然后在pom.xml文件中配置zookeeper依赖: 在resources目录下创建一个zk-connect.properties属性配置文件,我们在该文件中填写...

ZeroOne01
04/26
0
0
淘宝SOA框架dubbo学习(2)--搭建Zookeeper注册中心服务

继上一篇博文, 淘宝SOA框架dubbo学习(1) http://my.oschina.net/hanshubo/blog/374974 1、下载 Zookeeper 下载页面地址: http://www.apache.org/dist/zookeeper/zookeeper-3.4.6/ 注:下......

宁宁爸
2015/02/04
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

(三)Nginx配置·续

概述 前文写了关于Nginx环境配置,但是还没有完,接下来将会继续讲三个相关的配置 主要是以下三个 1.Nginx访问日志 2.Nginx日志切割 3.静态文件不记录日志和过期时间 Nginx访问日志 1.先看看...

杉下
今天
1
0
jquery创建类似于java的map

var map = {}; // Map map = new HashMap(); map[key] = value; // map.put(key, value); var value = map[key]; // Object value = map.get(key); var has = key in map; // boolean has = ......

SuperDabai
今天
0
0
java大数据转换16进制转10进制

public static void main(String[] args) {String hex = "0xdbf3accc683297cf0000";BigInteger amount = new BigInteger(hex.substring(2), 16);System.out.println(amount);......

任梁荣
昨天
2
0
OSChina 周六乱弹 —— 目测我们程序员丁克的几率不大

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @真Skr小机灵鬼儿:8.13分享Jocelyn Pook/Russian Red的单曲《Loving Strangers》 《Loving Strangers》- Jocelyn Pook/Russian Red 手机党少...

小小编辑
昨天
13
3
TypeScript基础入门 - 函数 - 剩余参数

转载 TypeScript基础入门 - 函数 - 剩余参数 项目实践仓库 https://github.com/durban89/typescript_demo.gittag: 1.2.1 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能...

durban
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部