skywalking插件开发的注意事项

最近蚂蚁金服中间件开源了 sofa 相关的部分组件,比如 rpc,欢迎大家参与讨论贡献,为 rpc 做链路适配的时候,skywalking 现在快到5.0版本了. 已经不支持 h2暂时,开发过程中了,环境的搭建.以下部分字段不能少.否则外面无法连接 es.

docker run -d -p 9200:9200 -p 9300:9300 -e "network.host=0.0.0.0" -e "transport.host=0.0.0.0"  -e "network.publish_host=0.0.0.0"  -e "xpack.security.enabled=false" -e "network.bind_host=0.0.0.0" -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:5.5.0

这条命令会搞定.

同时 application.yml 文件中

storage:
  elasticsearch:
    cluster_name: docker-cluster
    cluster_transport_sniffer: false
    cluster_nodes: localhost:9300
    index_shards_number: 2
    index_replicas_number: 0
    ttl: 70

这一段改一下.

其他的一些网上已有的文档,可以看看.SkyWalking 源码分析 —— 调试环境搭建

开发 

分析代码调用关系的利器-Flow

今天推荐一个不错的软件.是idea 的插件.名字是Flow, 官方称:A better way to understand your Java applications,原理就是通过 java-agent 修改字节码,配置了拦截器,然后真实地跑一个测试用例,或者启动一下项目,就会生成一个真实的调用关系.官方地址:http://findtheflow.io/

之前阅读源代码,对于抽象类,或者接口,静态阅读代码不太容易确定具体的调用类,因此阅读有一定的阻碍,当然 debug 也行..但是这个可以通过跑用例,或者简单的测试用例,理清调用关系,非常不错. 可以对代码结构有一个整体关系

安装

安装比较简单:https://plugins.jetbrains.com/plugin/8362?pr=idea 直接安装idea 这个插件,然后重新启动 idea, 安装完成后的效果.

安装结果

使用

使用更简单,直接点击上图中的按钮,开始跑一下,即可,如果启动成功.控制台会有显示.

开始启动

然后,会在本地开启7575的端口,来显示结果.

效果

结果

结果明细

注意,在结果页里,可以和 idea 源码交互,对着方法点右键,可以直接定位到 idea 代码中的源代码,非常方便.

跳转

其他

其他,就是 可以在配置里设置根据哪些类,这样一些工具类啥的可以直接忽略了.

运行配置

使用了一下,还是不错的.但是这个有个问题,如果你的项目自定义了 classloader/ 或者使用了自定义的容易,这个由于没有 mvn 的 jar 包,可能会报错,类找不到.暂时没有好的办法.但是阅读开源代码基本没有问题了.

java  工作 

jdk8_cannot_access_class_file

之前有个项目用 jdk6跑运行正常,用 jdk8跑的时候,会报java cannot access ....class file ...as class file not found though it exists. 虽然可以通过加上报错的类到依赖里解决.但是一直没想明白,为啥 jdk6下没报错.

最近再次遇到,于是想一次性搞清楚.搜了一下,看 so 上有这么个说法.大意就是以前,如果 A 依赖 B,B 实现了 C 接口,编译的时候, 用 jdk8编译的时候, C 必须在 classpath 中, http://stackoverflow.com/questions/40255718/compiling-with-jdk-1-8-java-cannot-access-class-file-class-file-not-found

给出了一个 bug 连接,但是这里跟我们的问题有差异,不过这个点提醒了我.于是我搜索了一下 jdk8的relase note

http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html

注意观看这一段:

Area: Tools / javac Synopsis Interfaces need to be present when compiling against their implementations

好了.也就是说还是乖乖加依赖.但是清楚了原因了

java  工作 

oom介绍

oom 之前知道, 但是并不是很了解,最近遇到了由 oom 引发的问题,所以学习记录一下. OOM-killer:Out-of-Memory (OOM) Killer是一种保护机制,用于当内存严重不足时,为了系统的继续运转,内核迫不得已挑选一个进程,将其杀死,以释放内存,缓解内存不足的问题。 可以看出这种方式对进程的保护是有限的,不能完全的保护进程的运行。 如何知道是否发生了 oom 两种方法,第一种,查看 /var/log/messages,会有类似 Out of memory: Kill process 9682 (mysqld) score 9 or sacrifice child Killed process 9682, UID 27, (mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB httpd invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0 httpd cpuset=/ mems_allowed=0 Pid: 8911, comm: httpd Not tainted 2.6.32-279.1.1.el6.i686 #1 这样的标识,说明发生了 oom,关键就是 kill process, 所以可以这样 sudo cat /var/log/messages | grep -i"killed process" 另一种是通过dmesg来查看 dmesg | egrep -i 'killed process' 这个命令查看的 oom 的时间里是时间戳的形式,如果你的 dmesg 没有-T这个时间的选项,那么就需要通过 [Read More]
java  工作 

graylog日记管理平台使用的那些坑

前言 最近使用 graylog在部署日志平台的时候,踩到很多”坑”,记录一下 日志采集(nxlog) 1.客户端不要做太多的正则计算 graylog 最早推荐的 nxlog 采集客户端,现在貌似有了 beats 的采集方式,不过我没了解,nxlog 采集的话,需要配置Snippets,就是定义输入,输出,处理器的地方,这个地方, Input 模块是在客户端计算的.所以,一定不要进行太多的正则计算.否则会严重影响客户端的 cpu 资源.降低应用程序的性能. 2.开多行一定要慎重 graylog 可以通过配置 <Extension multiline> Module xm_multiline HeaderLine /^\d{0,2}\/\d{0,2}\/\d{0,4}/ EndLine /^\d{0,2}\/\d{0,2}\/\d{0,4}/ </Extension> <Input pcc-esolutions-log> Module im_file File "*.log" SavePos TRUE InputType multiline </Input> 来实现对于类似错误栈这样的信息,将多行采集成一行,但是一定要注意.如果这个正则写错了,或者其他原因,导致,未能正确匹配.会导致 nxlog 客户端占用内存暴涨.原因是为了实现多行采集,会再客户端内存中保存日志内容,直到匹配到行尾.如果未能正确匹配.会一直保存.导致内存泄露. 这时候一般伴随着nxlog 的客户端日志中开始打印: 2016-12-05 18:36:47 ERROR oversized string, limit is 1048576 bytes 这样的信息.表示单条日志超过了1m 最终有一定几率影响客户端应用,被 oom 所杀.不要问我怎么知道的… 3 日志就是太大怎么办. 貌似没办法..只能在 Input 配置中. Exec if $raw_event $raw_event = substr($raw_event, 0, 1040000); 执行类似的来限制,没有尝试过,参考这里:日志大小超长配置 [Read More]
java  工作 

graylog中的mongodb配置

接手的一个工具平台,发现 graylog 集群使用了单个的 mongodb 作为数据库,于是需要配置一下集群,来防止数据丢失,毕竟很多配置都在里面. 为了以防万一,先备份一下 graylog 的配置. mongodump -h dbhost -d dbname -o dbdirectory 防止分布式部署的使用搞坏了.之后的恢复可以使用 mongorestore -h dbhost -d dbname --directoryperdb dbdirectory 来恢复.相关说明可以参考这里 之后就可以正式开始了 修改集群名字 在/etc/mongod.conf 中,修改这个值.设置集群使用的集群名称是 graylog,几个机器都配置一下.都先不要启动 replication: replSetName: graylog 然后添加集群配置 启动其中一台,然后通过mongo 命令连接上数据库,依次执行下面的命令.注意,这里有个坑.添加本机的时候,一定要写对外的域名或者 ip.否则会导致无法选主. rs.initiate() rs.add("<hostname>:27017") rs.add("<hostname>:27017") rs.add("<hostname>:27017") rs.conf() 开始启动 这里启动就不用说了. service mongod start 启动就好了. 配置 graylog 集群连接地址 在/etc/graylog/server/server.conf 中配置.mongodb_uri = mongodb://host1,host2,host3/graylog 后面这个 graylog 就是给 graylog 使用的库名,你可以先创建. 之后mongodb 就开始自行同步了. [参考] [Read More]
编程 

graylog中的字段解析

关于字段解析

一旦 graylog 用在了一个分布式系统上,那么采集的日志格式多种多样,涉及到通过 rules.drl来解析具体的字段.之前的同学的方案是用drools 来完成的.通过一个统一的界面,来给用户生成一些正则规则这种.然后自己写了个转换器转成 Drools 的文件.更新到 graylog 的服务器上.然后重启gralog 应用完成.

实际上, graylog 2之后的版本提供了rules和 pipeline ,这种不需要重启应用,完成这个解析的动作.但是.注意.这个不完善.所以只支持一些简单的语法,无法实现原有的完全转换.所以放弃.

在此过程中.这个rules 有一个比较强大的功能,自动解析 key value 对.需要添加,但是,需要你的日志文件格式里的 key value有空格, 也就是要求必须是 key=value 这样,不能紧挨着逗号这样的..比如你的打印日志是 key=value,key2=value2.那么久无法解析了..这个暂时没看到比较好的办法.估计要改代码.如果你恰好符合.那最好了.

java  工作 

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 "your_email@example.com",直接使用git的ssh key也是可以的.然后保存下面这个脚本为pscopy.sh, #!/bin/bash FILE=`cat ~/host.txt` for ip in $FILE;do expect -c " spawn ssh-copy-id $ipexpect { \"*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 "-$OPTARGneeds an argument" ;; k) key=$OPTARG ;; f) file=$OPTARG ;; *) echo "-$optnot recognized" usage ;; esac done if [ -z "$encoding" ]; then #该脚本必须提供-d选项 encoding="gbk" fi if [ -z "$file" ]; then #该脚本必须提供-d选项 file="~/hosts. [Read More]
java  学习  mac 

修改mac单应用创建线程的限制

最近遇到一个问题,公司的 java 服务端应用,启动后,通过 jstack pid |grep nid -c,可以看到大概创建了2044个线程,然后此时应用就会报错,提示无法创建更多线程, jvm 开始抛错. 查看 mac 的内存,发现还是够的.因为一般认为可创建的线程数=(总内存-其他占用的内存)/线程大小,所以内存够的情况下,应该是能创建的.

google 一圈,发现mac 对单线程创建的线程是有限制的.理由应该是为了保持系统稳定性.主要有两个参数

sysctl kern.num_threads 这个可以看一下,说明了系统能够创建的总共的线程,单个应用能够创建的线程是sysctl kern.num_taskthreads,第二个参数就是导致我们创建不出来更多线程的原因, 因为2044+一些 gc 的线程,基本上刚刚达到这个极限.

那么要么改程序,要么改参数.改程序这是不可能的..因为只有 mac 会有这个问题..该参数尝试通过sudo sysctl -w kern.num_taskthreads=4096,修改,会发现提示是只读属性.google 了一圈,无解.

最终意外解决..

参考这里开启性能模式

  1. nvram boot-args
  2. sudo nvram boot-args="serverperfmode=1 $(nvram boot-args 2>/dev/null | cut -f 2-)"
  3. 重启

如果想要恢复的话: sudo nvram boot-args="$(nvram boot-args 2>/dev/null | sed -e $'s/boot-args\t//;s/serverperfmode=1//')"

当时各种搜索,加打apple 支持电话.无解.搜索意外看到这个说明,说开启之后,可以支持更多服务应用之类的.猜测应该会改这个值..果然..改完之后,直接重启,这个限制会变成5000..完美解决..理论上,应该通过继续修改这个参数 是可以自定义这个值的.不过还没尝试.

homebrew缓慢解决方案

mac 下使用 homebrew 作为包管理工具是非常好的. brew 用来安装非 gui 界面的程序. cask 用来安装 gui 界面的程序.但是这两个是使用的源在国外.所以你懂得..

1.替换 homebrew 默认源

cd /usr/local
git remote set-url origin git://mirrors.ustc.edu.cn/brew.git

这里注意记一下以前的默认源.防止以后想换回来..

默认源是 https://github.com/Homebrew/brew

2.替换homebrew bottles默认源

echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.ustc.edu.cn/homebrew-bottles' >> ~/.bashrc

这里的.bashrc根据自己的情况替换.我是 zsh,就写到.zshrc 文件.