监控系统概要

监控系统 三剑客 metrics monitor alert 监控什么 主机级别 CPU Memory Disk space Processes 应用程序 Error and success rates Service failures and restarts Performance and latency of responses Resource usage 网络相关 Connectivity Error rates and packet loss Latency Bandwidth utilization 服务池资源 Pooled resource usage Scaling adjustment indicators Degraded instances 外部依赖的度量 Service status and availability Success and error rates Run rate and operational costs Resource exhaustion 如何采集Metrics 黄金指标 延迟 延迟可以知道一个任务需要多久 流量 知道系统的繁忙程度 错误 错误的分类和管理 饱和 资源的利用率 可以说,任何的组件都可以通过这四个指标进行监控 组件说明 服务器组件 To measure CPU, the following measurements might be appropriate: Latency: Average or maximum delay in CPU scheduler Traffic: CPU utilization Errors: Processor specific error events, faulted CPUs Saturation: Run queue length 应用程序与服务 Latency: The time to complete requests Traffic: Number of requests per second served Errors: Application errors that occur when processing client requests or accessing resources Saturation: The percentage or amount of resources currently being used ...

2021-07-03 · 2 min · bystander

mac日志批量查询配置

由于公司线下机器非常多,导致每次查日志变得非常痛苦.线下的trace平台大部分时候还是可用的.但是有时候需要本机来批量查询.方案就是批量分发ssh key,实现免登.然后luit实现编码转换,这个主要是公司的机器编码有差异.历史原因. 0. 准备 先要安装pssh,expect,ssh-copy-id. brew install pssh brew install homebrew/dupes/expect brew install ssh-copy-id 另外安装luit的安装参考这里luit安装 1. 生成ssh key ,并批量copy 生成ssh key比较简单.ssh-keygen -t rsa -C "[email protected]",直接使用git的ssh key也是可以的.然后保存下面这个脚本为pscopy.sh, #!/bin/bash FILE=`cat ~/host.txt` for ip in $FILE;do expect -c " spawn ssh-copy-id $ip expect { \"*yes/no*\" {send \"yes\r\";exp_continue} \"*password*\" {send \"pass\r\";exp_continue} \"*password*\" {send \"pass\r\";} } " done 然后执行一下sh pscopy.sh,注意,host.txt要保证存在.格式是user@address.一行一个,中间的paas要改成user的密码,这样就会使用指定的用户密码,自动copy ssh key了. 完成上面的步骤之后,ssh user@address 就可以免登了. 2. 写一个简单的pssh脚本 #!/bin/bash encoding= key= command= file= usage() { echo "Usage: `basename $0` [-f filename] [-c encoding] [-k keyword]" exit 1 } while getopts :f:c:k: opt do case $opt in c) encoding=$OPTARG ;; :) echo "-$OPTARG needs an argument" ;; k) key=$OPTARG ;; f) file=$OPTARG ;; *) echo "-$opt not recognized" usage ;; esac done if [ -z "$encoding" ]; then #该脚本必须提供-d选项 encoding="gbk" fi if [ -z "$file" ]; then #该脚本必须提供-d选项 file="~/hosts.txt" fi if [ -z "$key" ]; then #该脚本必须提供-d选项 usage fi command="pssh -h $file -P \"find /home/admin/logs/ -name '*.log'|xargs grep $key --col\"" luit -encoding "${encoding}" "${command}" 保存这个脚本为pssh.sh,然后用法如上.之后就可以通过 pssh.sh -f host.txt -c gbk -k keyword来批量查询了

2016-10-05 · 1 min · bystander

motan源码阅读-客户端服务引用

一旦服务器启动,服务开始提供,并且在配置中心注册了(配置中心可以是本地的地址,也可以是zk,也可以是其他的实现),那么客户端就要开始调用了 点击看大图 服务引用 RefererConfig.getRef() 先是获取集群支持(先忽略,主要是配置中心相关的) configHandler.refer(interfaceClass, clusters, proxy) 开始获取接口代理 1.一旦知道接口名,Class.forName加载接口类,就开始通过proxy工厂来为服务端接口创建代理了 2.jdk的Proxy类,直接来创建代理.同时代理要传入RefererInvocationHandler 这个类可以看错是真正的stub,封装了rpc调用请求.当在客户端获取到服务接口的bean的时候,实际上调用过程被这个类拦截,进行封装发送rpc 1.当接口被调用的时候,这个拦截器险根据拦截到的请求构造一个rpc请求 2.这里就会存在一个策略.该调用哪个,以FailoverHaStrategy为例 1.选择一个服务提供方 1.如果是jvm服务,那么直接从本地的服务map中取出一个调用就行 2.如果是真正的远程服务,这时候就进入nettyClient部分了 把请求向netty的Channel中写就行了.服务端会从Channel中取进行处理,然后放回来.这样客户端就拿到结果了

2016-05-31 · 1 min · bystander

motan源码阅读-服务的发布

这一篇继续从这个demo开始,分析一下这个服务是怎么发布出去的.关键的代码从motanDemoService.export();开始. 一图胜千言. 点击看大图 服务发布ServiceConfig.export() 1.加载有的配置中心url列表/新建 2.doExport(ProtocolConfig,port,registryURLs) //配置中心地址列表 2.1导出的时候,会先判断是否存在.其实就是根据协议名,ip,接口,参数来生成一个唯一key. 2.2ConfigHandler.export(Class interfaceClass, T ref, List registryUrls) //接口.实现.配置中心url列表 2.2.1.根据协议名创建协议,这里ProtocolFilterDecorator 2.2.2.根据接口,实现类,serviceUrl,构造一个Provider,用来提供服务 2.2.3.使用协议进行导出Provider, export(Provider provider, URL url) 2.2.3.1创建一个Exporter 2.2.3.1.1.创建的时候会将服务提供方Provider和url有个映射关系,这样当一个url请求过来的时候,就知道改调用谁了.ProviderMessageRouter,讲一个请求路由注册到server上,同时包装了一个心跳包 2.2.3.2进行导出 导出就是一个服务器打开的过程/server.open(); 2.2.3.2.1进入nettyServer初始化,主要就是添加handler,编码解码.和一个rpc处理的 相当于一个请求过来的时候,先进行解码,然后调用业务处理handler进行处理,处理完成后,进行编码,然后返回给客户端 服务器启动后,相当于这个服务就发布了 2.2.4.注册register(registryUrls, serviceUrl) //这一步就是将serviceUrl,向对应的jvm/rpc服务中心注册url,本地注册就是LocalRegistryService类里一个map..zk的.就是向zk写node.等等

2016-05-30 · 1 min · bystander

motan源码阅读-入门和运行demo

工作中一直在使用rpc,但是只是对简单的原理比较熟悉.最近看到有motan的一个介绍,代码拉下来看了看,除了测试用例比较少之外.其他还是不错的,和阿里的rpc框架比起来,还是弱了一些,好处就是方便用来学习. motan 是weibo的一个rpc框架,据说已经在线上使用了. 在学习rpc框架之前,建议看一个hello world级别的文章RPC框架几行代码就够了,写的非常好,看完基本就知道rpc的核心了. Remote Procedure Calls中最关键的那个图,就能说明了. 本地client调用本地client stub,stub对消息进行封装,通过socket发送,服务端的server stub接收到,然后解包,将里面传递的方法名,方法参数.等等信息,识别出来,调用服务端对应的服务,然后得到结果后,又通过socket返回,本地client又进行解包.就行了. 这里面会涉及到,封装,封装就是吧对象序列化,这样才能在网络中传递. 而生产环境的rpc框架需要考虑的有: stub怎么生成,序列化怎么最高效,如何统一不同机器之前的调用,(大小端的机器等),如何识别该调用哪个机器,负载均衡.socket通信.等等. 先跑个demo熟悉一下. 下载motan源码,导入ide,然后先启动服务端,MotanApiExportDemo,这个类,然后控制台会打出服务已经启动.然后运行MotanApiClientDemo,会发现一个控制台打出motan,服务端打出hello motan.就说明跑起来了. 如果控制台日志没有.修改对应resources下面的log4j.properties文件.首行添加log4j.rootLogger=debug,stdout ,会设置默认日志级别为debug,并且在控制台输出. 或者直接fork我这个 后面会逐步分析,希望坚持下来.

2016-05-29 · 1 min · bystander

motan源码阅读系列目录

本系列希望可以吧motan的源码通读一遍. motan源码阅读-入门和运行demo motan源码阅读-服务的发布 motan源码阅读-客户端服务引用

2016-05-29 · 1 min · bystander

ansible简单使用

由于线下机器太多.有没有日志平台,所以查询日志比较麻烦.发现了ansible,按照官方文档(ubuntu) $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible 一步步执行,第二步执行的时候,可能会报错 sudo: add-apt-repository: command not found 这时候.先执行 $ sudo add-apt-repository ppa:git-core/ppa $ sudo apt-get update 然后接着执行上面的第二步就行了.. 安装完成后,配置集群 cat /etc/ansible/hosts [servergroup1] 192.168.1.1 ansible_ssh_user=root ansible_ssh_pass=root [servergroup2] 192.168.2.1 ansible_ssh_user=root ansible_ssh_pass=root 后面的账号和密码,如果你使用ssh key登陆的话就不需要了.但是如果有很多机器,需要加到known_hosts就太多了. 这时候可以参考Batch_key 这个脚本.稍微修改一下,就能批量生成了 然后就是执行命令了 ansible常见用法为ansible host-pattern -m 模块 -a 命令,host-pattern类似于简化的正则表达式,而模块可以通过ansible-doc -l命令来查询。下面是一些常用模块的使用方法: 安装软件:ansible servergroup1 -m apt -a 'name=gcc state=present' 或者ansible local -m yum -a "name=nmap state=installed" 执行命令:ansible servergroup1 -m shell -a 'uptime' 拷贝文件:ansible servergroup1 -m copy -a 'src=/tmp/server dest=/tmp/server' 文件属性:ansible servergroup1 -m file -a 'dest=/tmp/server mode=755 owner=root group=root' 还有一个playbook的,看上去就是一个任务定义.我也暂时用不上.. 参考文档: http://docs.ansible.com/ansible/intro_installation.html http://lifeonubuntu.com/ubuntu-missing-add-apt-repository-command/ http://www.cnblogs.com/feisky/p/4102613.html

2016-03-25 · 1 min · bystander

python3.5 安装 Paramiko

最近由于一些需求,要搞一下python,于是周末搞了搞.要连接服务器,进行一些服务器的操作,于是安装这个Paramiko包, 直接pip install paramiko 结果.报错,最关键的一句是: error: Unable to find vcvarsall.bat google一圈.最终找到一种最简单地方法.其他的安装vs.安装MinGW都太复杂了. 安装PyCrypto 第三方版 因为paramiko依赖PyCrypto,上面那个错就是他报错出来的.安装PyCrypto第三方版 pip install --use-wheel --no-index --find-links=https://github.com/sfbahr/PyCrypto-Wheels/raw/master/pycrypto-2.6.1-cp35-none-win_amd64.whl pycrypto 安装完成后,再次安装paramiko即可. 2.修改nt.py 安装完上面的步骤,写一个简单的程序测试下 #-*- coding: utf-8 -*- #!/usr/bin/python import paramiko import threading def ssh2(ip,username,passwd,cmd): try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(ip,22,username,passwd,timeout=5) for m in cmd: stdin, stdout, stderr = ssh.exec_command(m) out = stdout.readlines() #屏幕输出 for o in out: print(o) print('%s\tOK\n'%(ip)) ssh.close() except : print('%s\tError\n'%(ip)) if __name__=='__main__': cmd = ['find /home/admin/logs/ -mtime +3 -name \'*.log.*\' -exec rm -rf {} \;']#你要执行的命令列表 username = "admin" #用户名 passwd = "password" #密码 threads = [] #多线程 ip = "127.0.0.1" print("Begin......") a=threading.Thread(target=ssh2,args=(ip,username,passwd,cmd)) a.start() input() 运行报错. ImportError: No module named 'winrandom' so一下..找到一个办法 http://stackoverflow.com/questions/24804829/another-one-about-pycrypto-and-paramiko 找到python3.5的安装目录的 Lib\site-packages\Crypto\Random\OSRNG的nt.py文件将 import winrandom 改成 from . import winrandom 再次运行ok.非常简单

2015-12-28 · 1 min · bystander

json-lib反序列化精度丢失问题

最近在工作中,遇到一个问题,项目中某处使用了json-lib的2.4-jdk15版本.问题最终简化为 double amount = 6264583.33; String jsonString = "{\"pi\":" + amount + "}"; JSONObject jsonObject = JSONObject.fromObject(jsonString); System.out.println("转换前:" + jsonString); System.out.println("转换后:" + jsonObject); 这个值输出的将会是6264583.5 这个值.这个问题.先google一下,很快赵到了 http://sourceforge.net/p/json-lib/bugs/116/ 于是,大概问题知道了.是json-lib的一个bug,但是这个bug怎么来的呢.结合这个bug下面的评论和debug代码,先以pi这个例子,很快走到了. 可以看到json-lib走到了apache common-lang(2.5这个版本) 的NumberUtils.createNumber处,此时String的还是对的. 继续单步,来到这个方法里面 可以看到这里小数部分,整数部分也都还是对的.继续向下走.我擦.画风不太对.居然采用了先尝试float,发现没问题.然后就继续尝试double,我擦.直接数据就丢失了呀.. 好吧..那么现在问题就便成了更简单的一个问题. 使用NumberUtils.createNumber 的bug.在bug issue里,有人提到.这个bug,apache官方已知.好的. https://issues.apache.org/jira/browse/LANG-693 然后在这里有官方的一次修复,修复记录在这里.3.2版本已经修复. http://svn.apache.org/viewvc?view=revision&revision=1484263 可以看到是对小数部分的长度进行了判断.如果小于7位,就用float转换,如果大于7,小于16,就用double,如果还大,就用BigDecimal. n = org.apache.commons.lang3.math.NumberUtils.createNumber("3.14159265358"); System.out.println("lang3_createNumber_3.14159265358---->" + n + "->精度正常"); 于是我继续debug,看common-lang3的修复情况,好像确实是修复了.但是对于我出现的问题1.6264583.33 这个数字,还是出现了精度丢失,因为这里小数部分小于7位,所以尝试使用float转换,直接丢失精度 修复不完善.. 于是提个bug :https://issues.apache.org/jira/browse/LANG-1187 等回复. 继续.公司内部一般使用fastjson,那么如果我使用fastjson,有问题吗? 发现没有问题. Object o = com.alibaba.fastjson.JSONObject.parse("3.14159265358"); System.out.println("fastjson_createNumber_3.14159265358---->" + o + "->精度正常"); o = com.alibaba.fastjson.JSONObject.parse("6264583.33"); System.out.println("fastjson_createNumber_6264583.33---->" + o + "->精度正常"); 可以看到,这里做转换的时候传递了一个是否是bigdecimal的标识.而这个标识默认是开启的.而且即使不开启.. 最坏的情况也是个double.所以数据不会丢失. 再顺便说一下,double的6264583.33 为什么转换到float会精度丢失,先看一下浮点数在计算机中怎么表示的 找到一张图,这是double的标识和浮点数的计算. 而浮点数则是32位,1位符号位,8位幂,23位尾数,看测试代码 //double标识测试 double d = 6264583.33d; long l = Double.doubleToLongBits(d); System.out.println(Long.toBinaryString(l)); //float想要表示这个数字 float f = 6264583.33f; int value = Float.floatToIntBits(f); System.out.println(Integer.toBinaryString(value)); //double表示这个值 d = 6264583.5d; l = Double.doubleToLongBits(d); System.out.println(Long.toBinaryString(l)); 输出结果(做一下分割对齐) 1 00000101010 111111001011100000111010101000111101011100001010010 1 00101010 1111110010111000001111 1 00000101010 111111001011100000111100000000000000000000000000000 注意看,第一行是6264583.33的double表示.而同样想要用float表示这个数字,发现幂,符号位,都是对的.但是因为尾数只有23位,所以四舍五入,将完整double的后几位进位1,变成了这个二进制表示法,这时候已经不准确了, 而这个数字呢.看第三行,会发现实际上是6264583.5的精确值表示.尾数位0都是可以省略的,因为按照公式计算也没啥作用. 如有问题,欢迎评论讨论. 附录: 完整的测试代码 public class App { public static void main(String[] args) { //http://sourceforge.net/p/json-lib/bugs/116/ //2.4版本有问题 double pi = 3.14159265358; String jsonString = "{\"pi\":" + pi + "}"; JSONObject jsonObject = JSONObject.fromObject(jsonString); System.out.println("转换前:" + jsonString); System.out.println("转换后:" + jsonObject); double amount = 6264583.33; jsonString = "{\"pi\":" + amount + "}"; jsonObject = JSONObject.fromObject(jsonString); System.out.println("转换前:" + jsonString); System.out.println("转换后:" + jsonObject); //测试2.4版本引入的lang,这里面 Number n = org.apache.commons.lang.math.NumberUtils.createNumber("3.14159265358"); System.out.println("lang2_createNumber_3.14159265358---->" + n + "->精度丢失"); n = org.apache.commons.lang.math.NumberUtils.createNumber("6264583.33"); System.out.println("lang2_createNumber_6264583.33---->" + n + "->精度丢失"); //测试3.4版本,里面是根据小数部分的长度,选择是否使用float还是double,当小数部分大于7的时候,就会使用double n = org.apache.commons.lang3.math.NumberUtils.createNumber("3.14159265358"); System.out.println("lang3_createNumber_3.14159265358---->" + n + "->精度正常"); //这种情况就会有问题,虽然小数部分是33,两位,但是实际上是个浮点数.所以还会丢失精度 n = org.apache.commons.lang3.math.NumberUtils.createNumber("6264583.33"); System.out.println("lang3_createNumber_6264583.33---->" + n + "->精度丢失"); //测试fastjson Object o = com.alibaba.fastjson.JSONObject.parse("3.14159265358"); System.out.println("fastjson_createNumber_3.14159265358---->" + o + "->精度正常"); o = com.alibaba.fastjson.JSONObject.parse("6264583.33"); System.out.println("fastjson_createNumber_6264583.33---->" + o + "->精度正常"); //double标识测试 double d = 6264583.33d; long l = Double.doubleToLongBits(d); System.out.println(Long.toBinaryString(l)); //float想要表示这个数字 float f = 6264583.33f; int value = Float.floatToIntBits(f); System.out.println(Integer.toBinaryString(value)); //double表示这个值 d = 6264583.5d; l = Double.doubleToLongBits(d); System.out.println(Long.toBinaryString(l)); } }

2015-11-25 · 2 min · bystander

zookeeper伪集群部署

zookeeper是用来管理分布式环境的系统主要用来服务发现,配置管理,同步.大致原理是zookeeper 自身集群的每个节点都维护这一个目录树,内容相同,每个节点的数据一致性由zookeeper自身的算法来解决.下篇尝试.zookeeper本篇主要说明如果部署zookeeper的分布式环境. 下载 zookeeper由apache在管理,下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/.下载完成后,随便放个目录好了.. 配置 本次创建3个节点. 1 . 存储目录准备 首先给每个伪节点创建一个目录.用来存储每个节点保存的目录信息.真实的分布式环境将对应在不同的机器上. 这里我在D:\zookeeper,创建三个目录,分别是zk1,zk2,zk3. 然后为每个集群编写一个myid文件,标识集群id 2 . 启动配置文件 下载完成后,在conf目录会看到由一个zoo_sample.cfg实例配置文件,我们可以以这个为模板.来为分布式环境的每个zookeeper节点配置一个节点的数据目录,端口.其他节点的信息等. 我们在conf目录例创建三个配置文件,分别为zk1.cfg,zk2.cfg,zk3.cfg; 里面的值 zk1.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk1 clientPort=2181 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 zk2.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk2 clientPort=2182 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 zk1.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=D:/zookeeper/zk3 clientPort=2183 server.1=127.0.0.1:2888:3888 server.2=127.0.0.1:2889:3889 server.3=127.0.0.1:2890:3890 这里的server.1.2.3这就是每个机器对应的myid的值. server.1=127.0.0.1:2888:3888解释一下这条配置.前面的2888是各个节点用来互相交流.选取leader的端口.后面这个端口,3888是各个节点用来和leader沟通的节点.而clientPort 是开放出去,等待客户端连接的端口. 启动 分别启动三个实例,在zookeeper的安装目录下.进如bin目录,复制三个zkServer.cmd 文件,要是linux就不用这么麻烦了.. 分别加上一行 set ZOOCFG=../conf/zk1.cfg 最终这个文件像这样 setlocal call "%~dp0zkEnv.cmd" set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain set ZOOCFG=../conf/zk1.cfg echo on java "-Dzookeeper.log.dir=%ZOO_LOG_DIR%" "-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%" -cp "%CLASSPATH%" %ZOOMAIN% "%ZOOCFG%" %* endlocal 然后直接双击启动zkServer1.cmd,zkServer2.cmd,zkServer3.cmd 刚启动第一个之后,你会看到有报错,是zookeeper进行选举的时候报错的.因为第一个zk节点.从自己的启动配置里,知道还有两个节点,于是尝试连接.但是连接不上,再启动另外两个.都启动后,报错消失 然后在D:\zookeeper中可以看到由数据写入. 测试 启动bin目录的zkCli.cmd,自动连接本机的2181端口.也可以自己指定 zkCli.cmd –server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183 对客户端来说.连接上了一个列表之后,如果一台挂了,并不会影响.系统依旧可以运行. 然后执行一些简单的操作 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容。 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据。 创建文件,并设置初始内容: create /zktest “test” 创建一个新的 znode节点“ zk ”以及与它关联的字符串。 获取文件内容: get /zktest 确认 znode 是否包含我们所创建的字符串。 修改文件内容: set /zktest “zkbak” 对 zk 所关联的字符串进行设置。 删除文件: delete /zktest 将刚才创建的 znode 删除。 退出客户端: quit 帮助命令: help 可以关掉一个服务器,会发现客户端依然正常.可以执行get set等操作.

2015-11-22 · 1 min · bystander