kafka0.8.1

一 问题

10月22号应用系统忽然报错:

[2014/12/22 11:52:32.738]java.net.SocketException: 打开的文件过多

[2014/12/22 11:52:32.738]       at java.net.Socket.createImpl(Socket.java:447)

[2014/12/22 11:52:32.738]       at java.net.Socket.connect(Socket.java:577)

[2014/12/22 11:52:32.738]       at java.net.Socket.connect(Socket.java:528)

[2014/12/22 11:52:32.738]       at sun.net.NetworkClient.doConnect(NetworkClient.java:180)

[2014/12/22 11:52:32.738]       at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)

[2014/12/22 11:52:32.738]       at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)

[2014/12/22 11:52:32.738]       at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)

[2014/12/22 11:52:32.738]       at sun.net.www.http.HttpClient.New(HttpClient.java:308)

[2014/12/22 11:52:32.738]       at sun.net.www.http.HttpClient.New(HttpClient.java:326)

[2014/12/22 11:52:32.738]       at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:996)

[2014/12/22 11:52:32.738]       at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:932)

[2014/12/22 11:52:32.738]       at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:850)

[2014/12/22 11:52:32.738]       at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)

[2014/12/22 11:52:32.738]       at com.rbc.http.client.RbcHttpClient.callCptService(RbcHttpClient.java:50)

[2014/12/22 11:52:32.738]       at com.rbc.http.client.RbcHttpClient.callCptService(RbcHttpClient.java:144)

[2014/12/22 11:52:32.738]       at com.rbc.http.bean.BaseBean.call(BaseBean.java:54)

[2014/12/22 11:52:32.739]       at app.package.APPClass.send2Center(APPClass.java:852)

[2014/12/22 11:52:32.739]       at sun.reflect.GeneratedMethodAccessor4312.invoke(Unknown Source)

[2014/12/22 11:52:32.739]       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

[2014/12/22 11:52:32.739]       at java.lang.reflect.Method.invoke(Method.java:606)

[2014/12/22 11:52:32.739]       at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)

[2014/12/22 11:52:32.739]       at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)

[2014/12/22 11:52:32.739]       at com.sun.proxy.$Proxy157.send2Center(Unknown Source)

[2014/12/22 11:52:32.739]       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)

[2014/12/22 11:52:32.739]       at java.util.concurrent.FutureTask.run(FutureTask.java:262)

[2014/12/22 11:52:32.739]       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

[2014/12/22 11:52:32.739]       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

[2014/12/22 11:52:32.739]       at java.lang.Thread.run(Thread.java:745)

发现是因为上午打开一个开关,即应用系统将访问日志发送到消息平台kafka,但是应用系统服务器没有配置消息平台kafka的host,导致出现问题;

二 问题重现

将kafka客户端的broker-list配置为一个不存在的host,并且不断发送消息,执行:

lsof –p $pid|wc -l

会发现该java进程的文件描述符不断增长,其中包含大量的socket连接,并最终超过限制,可以通过:

ulimit -a|grep 'open files'

来查看文件描述符数量限制,超出限制之后,会就不断报错:

java.net.SocketException: Too many open files

问题重现;

但是如果将broker-list配置为一个不存在的ip,则不能重现问题;

三 背景

1 File Descriptor

Generally, a file descriptor is an index for an entry in a kernel-resident array data structure containing the details of open files. In POSIX this data structure is called a file descriptor table, and each process has its own file descriptor table. The process passes the file descriptor to the kernel through a system call, and the kernel will access the file on behalf of the process. The process itself cannot read or write the file descriptor table directly.

On Linux, the set of file descriptors open in a process can be accessed under the path /proc/PID/fd/, where PID is the process identifier.

ulimit -a|grep 'open files'

查看进程文件描述符限制

cat /proc/sys/fs/file-max

查看系统总的文件描述符限制

lsof –p $pid

查看某个进程具体打开的文件描述符

ulimit –n $num

临时修改文件描述符限制

2 Kafka Async Producer

为了避免kafka出现问题影响应用系统,使用kafka异步producer,发送消息后会将消息添加到内存队列并立即返回,另外有一个线程不断处理内存队列中的消息并发送到kafka:

当kafka服务器出现问题,消息发送不出去的时候,只要配置queue.enqueue.timeout.ms=0,则内存队列满时消息直接抛弃掉,不会阻塞:

四 问题原因

Kafka客户端发送消息前,首先会通过broker-list中的配置连接到任一台broker获取metadata:

ERROR [2014-12-22 14:05:04,687] (Logging.scala:103)  - Producer connection to $kafka_server_1:9096 unsuccessful

java.nio.channels.UnresolvedAddressException

at sun.nio.ch.Net.checkAddress(Net.java:127)

at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:613)

at kafka.network.BlockingChannel.connect(BlockingChannel.scala:57)

at kafka.producer.SyncProducer.connect(SyncProducer.scala:141)

at kafka.producer.SyncProducer.getOrMakeConnection(SyncProducer.scala:156)

at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:68)

at kafka.producer.SyncProducer.send(SyncProducer.scala:112)

at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:53)

在这个过程报错UnresolvedAddressException,SyncProducer部分代码如下:

BlockingChannel代码如下:

发现问题原因:BlockingChannel的connect方法中,channel.connect这行抛异常,此时connected为false,但是SyncProducer的disconnect中只有当BlockingChannel的connected为true时才会调用BlockingChannel的disconnect方法,所以导致一直在调用Blockingchannel的connect方法而没有调用disconnect方法,而connect方法中会调用SocketChannel.open方法:

->

->

->

可见每次调用SocketChannel.open方法都会创建一个文件描述符,这样文件描述符会不断增加,为什么只有配host时出问题,而配ip时没有问题,SocketChannelImpl部分代码:

当配host时,是Net.checkAddress时抛UnresolvedAddressException异常,这时直接退出;当配ip时,是在Net.connect时抛ConnectionTimeoutException异常,这时会有后续的finally和catch代码执行,其中readerCleanup代码如下:

->

可见虽然没有调用disconnect,也会关闭文件描述符,所以配ip时不会出现文件描述符过多的问题;

五 修复

修改kafka.network.SocketChannel代码如下:

增加try-catch,并在UnresolvedAddressException异常发生时调用disconnect,问题解决;

这是当时发现问题之后在kafka jira上提交的issues: https://issues.apache.org/jira/browse/KAFKA-1832

【原创】大叔问题定位分享(5)Kafka客户端报错SocketException: Too many open files 打开的文件过多的更多相关文章

  1. nfs客户端报错解决Stale file handle

    NFS故障: 场景:客户端挂载是好的.服务端磁盘满了,重新给挂了一快.客户端df -h nfs挂载消失. 客户端报错:Stale file handle 现象如下: [root@test63-spri ...

  2. linux下svn客户端报错Cannot negotiate authentication mechanism的解决方法

    svn客户端报错Cannot negotiate authentication mechanism的解决方法: 问题出现的原因之一: 因为SVN服务器配置了saslauthd服务用来实现与ldap的对 ...

  3. [svc]nfs客户端报错解决Stale file handle

    NFS故障: 问题背景: 客户端挂载是好的.服务端磁盘满了,重新给挂了一快.客户端df -h 发现nfs挂载消失. 查看目录客户端报错:Stale file handle 现象如下: [root@n1 ...

  4. kafka启动报错&问题解决

    kafka启动报错&问题解决 一早上班,就收到运维同事通知说有一台物理机宕机,导致虚拟机挂了.只得重启kafka服务器. 1.启动 启动zookeeper bin/zkServer.sh st ...

  5. (未解决)flume监控目录,抓取文件内容推送给kafka,报错

    flume监控目录,抓取文件内容推送给kafka,报错: /export/datas/destFile/220104_YT1013_8c5f13f33c299316c6720cc51f94f7a0_2 ...

  6. Kafka 启动报错java.io.IOException: Can't resolve address.

    阿里云上 部署Kafka 启动报错java.io.IOException: Can't resolve address. 本地调试的,报错 需要在本地添加阿里云主机的 host 映射   linux ...

  7. 【原创】大叔问题定位分享(4)Kafka集群broker节点从zookeeper上消失

    kafka_2.8.0-0.8.1 一 现象 生产环境一组kafka集群经常发生问题,现象是kafka在zookeeper上的broker节点消失,此时kafka进程和端口都在,然后每个broker都 ...

  8. 【原创】大叔问题定位分享(3)Kafka集群broker进程逐个报错退出

    kafka0.8.1 一 问题现象 生产环境kafka服务器134.135.136分别在10月11号.10月13号挂掉: 134日志 [2014-10-13 16:45:41,902] FATAL [ ...

  9. 【原创】大叔问题定位分享(9)oozie提交spark任务报 java.lang.NoClassDefFoundError: org/apache/kafka/clients/producer/KafkaProducer

    oozie中支持很多的action类型,比如spark.hive,对应的标签为: <spark xmlns="uri:oozie:spark-action:0.1"> ...

随机推荐

  1. whereis、which、find的区别

    which用于查找可执行文件的目录,我们平时执行的命令实际上是一个可执行文件,如ls命令实际上是/usr/bin/目录下的一个可执行文件.它实际上是通过 PATH环境变量来查找的. whereis用于 ...

  2. 【翻译】IdentityServer4:基于资源的配置

    这篇文章基于https://leastprivilege.com/2016/12/01/new-in-identityserver4-resource-based-configuration/进行翻译 ...

  3. mybatis中使用到的设计模式

    Mybatis中使用到了哪些设计模式呢?下面就简单的来介绍下: 1.构造者模式: 构造者模式是在mybatis初始化mapper映射文件的过程中,为<cache>节点创建Cache对象的方 ...

  4. zabbix异常信息修改已确认,为未确认

    问题知悉只能知悉一次知悉了之后就不能再次知悉了,但又不想再创建新的异常怎么办呢.....直接改数据库数据.首先找到acknowledges表这里边存放的全是已经知悉的异常然后找events表,even ...

  5. mysql-笔记-数据类型

    https://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html serial: SERIAL is an alias for BI ...

  6. Python——Pycharm安装、激活、中文、

    1.激活pycharm (1) 修改hosts文件:将  0.0.0.0 account.jetbrains.com   添加到文件最后面   Windows系统hosts文件路径为:  c:\win ...

  7. Nginx 处理Http请求简单流程

    L45 1:三次握手后 系统内核收到请求根据端口负载均衡的分配到某个worker 2:nginx 会分配一个512byte链接内存池 3:初始化nginx的http模块并等待用户请求,假设用户在cli ...

  8. mybatis中的几个注意的地方

    1.首先定义一个sql标签,一定要定义唯一id<sql id="Base_Column_List" >name,age</sql>2.然后通过id引用< ...

  9. Java【第九篇】异常处理

    异常概述 介绍 任何一种程序设计语言设计的程序在运行时都有可能出现错误,例如除数为0,数组下标越界,要读写的文件不存在等等.捕获错误最理想的是在编译期间,但有的错误只有在运行时才会发生.对于这些错误, ...

  10. 金融量化分析【day110】:金融基础知识

    一.股票 股票: 股票是股份公司发给出资人的一种凭证,股票的持有者就是股份公司的股东. 股票的面值与市值 面值表示票面金额 市值表示市场价值 上市/IPO: 企业通过证券交易所公开向社会增发股票以募集 ...