package com.sf.monitor.zk; import com.google.common.base.Function; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.sf.log.Logger; import com.sf.monitor.Config; import com.sf.monitor.Resources; import com.sf.monitor.utils.JsonValues; import com.sf.monitor.utils.Utils; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.util.List; import java.util.Map; public class ZookeeperHosts { private static final Logger log = new Logger(ZookeeperHosts.class); private static final String StatCommand = "stat"; private static final String MntrCommand = "mntr"; private static final String RuokCommand = "ruok"; private final List<ZookeeperHost> zkHosts; public ZookeeperHosts(String addrs) { this.zkHosts = Lists.transform( Lists.newArrayList(addrs.trim().split(",")), new Function<String, ZookeeperHost>() { @Override public ZookeeperHost apply(String input) { String[] ss = input.trim().split(":", 2); return new ZookeeperHost(ss[0], Integer.valueOf(ss[1])); } } ); } public List<JsonValues> hostInfos() { return Lists.transform( zkHosts, new Function<ZookeeperHost, JsonValues>() { @Override public JsonValues apply(ZookeeperHost host) { return host.getInfo(); } } ); } public String sendCommand(String host, String cmd) { for (ZookeeperHost zkHost : zkHosts) { if (zkHost.toString().equals(host)) { return zkHost.command(cmd); } } return String.format("Zookeeper host [%s] not found!", host); } public void pulse() { for (ZookeeperHost host : zkHosts) { host.pulse(); } } static class ZookeeperHost { public String hostName; public int port; private boolean problem; public ZookeeperHost(String hostName, int port) { this.hostName = hostName; this.port = port; } @Override public String toString() { return hostName + ":" + port; } public void pulse() { String reply = command(RuokCommand); if (!"imok".equals(reply)) { String warnMsg = String.format("zookeeper host[%s] ping reply: [%s]", toString(), reply); Utils.sendNotify("zookeeper", warnMsg); log.warn(warnMsg); } } public boolean isOk() { return "imok".equals(command(RuokCommand)); } public JsonValues getInfo() { String infoMsg = command(MntrCommand); Map<String, String> metrics = Maps.newHashMap(); for (String kvStr : infoMsg.split("\n")) { if (kvStr.isEmpty()) { continue; } String[] kv = kvStr.split("\t"); if (kv.length == 2) { metrics.put(kv[0], kv[1]); } } metrics.put("isOk", isOk() ? "ok" : "error"); metrics.put("host", toString()); return JsonValues.of( metrics, "host", "isOk", "zk_server_state", "zk_version", "zk_avg_latency", "zk_max_latency", "zk_min_latency", "zk_packets_received", "zk_packets_sent", "zk_outstanding_requests", "zk_znode_count", "zk_watch_count", "zk_ephemerals_count", "zk_approximate_data_size", "zk_followers", "zk_synced_followers", "zk_pending_syncs", "zk_open_file_descriptor_count", "zk_max_file_descriptor_count" ); } public String command(String command) { // Try 10 times if we face "Connection reset" error. String resp = null; for (int i = 0; i < 10; i++) { resp = doCommand(command); if (!"Connection reset".equals(resp)) { return resp; } } return resp; } public String doCommand(String command) { Socket s = null; try { s = new Socket(); s.setSoLinger(false, 10); s.setSoTimeout(20000); s.connect(new InetSocketAddress(hostName, port)); IOUtils.write(command, s.getOutputStream()); return IOUtils.toString(s.getInputStream()); } catch (IOException e) { log.warn(e, "send 4TLR command [%s] to [%s:%d] error", command, hostName, port); return e.getMessage(); } finally { IOUtils.closeQuietly(s); } } } public static void main(String[] args) throws Exception { Config.init("config"); Resources.init(); final ZookeeperHosts host = new ZookeeperHosts("192.168.10.60:2181,192.168.10.41:2181,192.168.10.42:2181"); System.out.println("series: " + Resources.jsonMapper.writeValueAsString(host.hostInfos())); } }