「strace追踪java」java代码追踪

博主:adminadmin 2023-03-18 22:02:07 388

本篇文章给大家谈谈strace追踪java,以及java代码追踪对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java subscribe监听超时怎么解决

问题描述

redis提供了pub/sub功能,但在使用phpredis的subscribe时发现这样一个问题,代码如下(sub.php):

?php/*监听demo频道,打印收到的信息*/function process($redis, $chan, $msg){

var_dump($msg);

}$redis = new Redis();$res = $redis-connect('127.0.0.1', '7979');$redis-subscribe(array('demo'), 'process');123456789

代码运行后,发现如果在一段时间内未收到来自demo频道的消息,则会报如下错误:

PHP Fatal error:  Uncaught exception 'RedisException' with message 'read error on connection' in sub.php:11Stack trace:#0 /search/ballqiu/sub.php(11): Redis-subscribe(Array, 'process')#1 {main}

thrown in sub.php on line 1112345

原因分析

为了查找原因,我们使用strace对代码进行了跟踪:

strace php sub.php1

截取部分重要输出如下:

//连接redis

connect(3, {sa_family=AF_INET, sin_port=htons(7979), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)

//发送subscribe命令

sendto(3, "subscribe  demo\r\n", 17, MSG_DONTWAIT, NULL, 0) = 17//收到响应

recvfrom(3, "*3\r\n$9\r\nsubscribe\r\n$4\r\ndemo\r\n:1\r"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)

//套机字超时时间设为60s

poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 0 (Timeout)

//等待超时,关闭连接

close(3)                                = 0//输出错误信息

write(2, "PHP Fatal error:  Uncaught excep"..., 261PHP Fatal error:  Uncaught exception 'RedisException' with message 'read error on connection' 12345678910111213

可见报错的本质是poll设置接收超时所致,从starce结果我们知道这个超时默认是60s。

解决

我们有两种方法改变超时 

- 方法1 

在代码起始处设置

ini_set('default_socket_timeout', -1);1

方法2 

在redis connect后执行

$redis-setOption(Redis::OPT_READ_TIMEOUT, -1);1

两种方法中的-1均表示永不超时,你也可以将超时设置为自己希望的时间。 

无论使用哪种方法,再次strace, 你会发现poll的超时被设为了-1。

recvfrom(3, "*3\r\n$9\r\nsubscribe\r\n$4\r\ndemo\r\n:1\r"..., 8192, 0, NULL, NULL) = 33poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)

//超时被设为-1, 即永不超时

poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, -11234

个人比较推荐方法2,它只影响到redis本身。而方法1会对其它方法产生影响,比如 

file_get_contents等。

总结

使用phpredis的subscribe时,默认60内没有收到消息,sub端就会因超时异常退出。可以自行设置延长超时时间或永不超时。

df-h命令卡住

df,h命令卡住解决办法:

1、首先就是使用strace去追踪到底在哪里卡住了。

2、如果没有strace命令则进行安装即可。

3、显示出卡住的地方。

4、重启卡住的服务。

5、重启完即可正常使用df,h。

一次/etc/hosts权限错误导致的es集群错误

先说一下环境:系统使用的CentOS7.5,elasticsearch版本是5.4.0。一套产品集群包括三个elasticsearch节点构成的集群。

部署了两套测试集群,配置基本类似,elasticsearch配置文件中使用主机名。在某一次测试后,一套集群里的elasticsearch就开始报错,无法提供服务。查看日志发现,elasticsearch一直抛出UnknownHostException异常,所以无法和另外两个节点通信连成集群。根据堆栈信息,这个异常是在解析其它elasticsearch节点域名的时候调用InetAddress.getAllByName()抛出的。

而另外一套集群里类似的配置,它的elasticsearch服务却是很正常的。唯一的不同是,出问题的集群临时配置了DNS服务。

按正常的情况来说,elasticsearch解析域名的方式应该是先从/etc/hosts中获取,获取不到了再查询DNS。elasticsearch服务节点的主机名、IP都有在配置在/etc/hosts中。所以,即使一套集群配置了DNS,另外一套没有,也不应该出现elasticsearch无法解析域名的问题。

为了找到域名解析错误的原因,我决定跟踪一下elasticsearch解析域名的过程,使用的工具是strace。strace命令可以追踪进程的系统调用。

安装过程很简单。

接着是修改elasticsearch的执行脚本,一般路径是/usr/share/elasticsearch/bin/elasticsearch。在这个脚本的最后几行,在exec 后添加strace命令 strace -o /tmp/es.strace.log -f ,如下所示。

-o参数将strace的输出保存到文件/tmp/es.strace.log,-f参数表明追踪进程的所有子进程的系统调用。

两个集群的elasticsearch节点都修改了这个脚本,重启服务后对比查看。对比这个输出文件,终于发现一些端倪。首先,elasticsearch调用的getAllByName()确实首先查看了/etc/hosts文件,但是权限不足无法访问这个文件。

这是有问题的,首先是这个文件应该是可读的,不应该出现权限不足的问题,第二是两个集群都无法访问这个文件,但是为什么一个能解析域名而另外一个不能。

接着往下对比,出问题的elasticsearch进程这时候检查到/etc/resovl.conf文件已经配置,于是向DNS服务器发出了查询。DNS无法解析,于是抛出了UnknownHostException异常。另外一边,没有问题的elasticsearch进程检查到/etc/resovl.conf未配置,这时候做了一个特别的操作,它创建了一个地址族是AF_NETLINK的原始套接字,通过这个套接字查询得到了域名对应的IP地址。我猜测,这可能是访问系统的ARP信息。

既然是DNS的问题,那么把出问题的/etc/resolv.conf中的DNS配置删除呢?重启服务之后,elasticsearch服务依然抛出异常,查看日志发现进程虽然跳过了/etc/resolv.conf,但是它却开始访问了本地的DNS端口53(UDP),可能这是java最后的解析尝试了。恰好,这个节点上部署了rpcbind服务,这个服务恰好就监听了53端口,结果就是依然无法通过DNS解析,java华丽丽的抛出了异常。

问题的根本原因还是/etc/hosts文件不可读,查看这个文件的权限,结果是600,意思就是只能root用户读写了,其它用户没有任何权限,包括读。elasticsearch服务使用的elasticsearch用户,所以当然就会被禁止读取。

经过其它的查找,发现是有一个服务进程会一直更新这个hosts文件,更新的方式是先创建一个临时文件,然后rename成hosts文件,由于临时文件的默认权限是600,所以导致hosts文件的权限最后也是600了。

至此,整个的问题的原因已经清楚。hosts权限的错误,导致elasticsearch通过DNS解析域名,又刚好DNS解析报错,没有通过ARP解析域名。

另外从这个事情中也可以看到java解析域名的套路,先/etc/hosts文件,接着是DNS,先远程的DNS后本地的DNS,最后尝试从本地ARP缓存解析,中间有一个过程抛出异常的时候,解析就会失败。

关于strace追踪java和java代码追踪的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。