问题研究

项目中需要利用DataImportHandler从hive中sync数据到solr。发现有时候hive sql已经执行完几个小时了,sync任务还没有完成,貌似哪里卡住了。重启solr后重新sync又成功了,所以之前虽然遇到很多次这个问题也没有去深究。今天又出现了同样的问题,决定花点时间研究下到底是什么原因造成的。

利用jstack dump了几遍线程栈,发现很多个线程都卡在同一个地方,at java.net.SocketInputStream.socketRead0(Native Method),显然这些进程都在等待jdbc从hive中读取数据。初步判断可能是网络原因导致网络中断,TcpIp没有侦测到连接已经失败,我们在data-config.xml中配置hive数据源的时候又没有设置超时时间,导致线程一直傻傻等待接收数据sync任务一直无法完成,也没有任何异常抛出。之所以问题出现的这么频繁应该是因为我们的hive服务器设在美国,而solr服务器在国内。看来加上超时时间是很有必要的,难怪很多文章都提到为了不让比较慢的客户端拖垮服务器程序的性能必须加上超时时间。这些无限等待的线程都是在做无用功啊,又浪费服务器资源,设置超时时间后就会在超时时间到达时抛出timeout异常,退出线程。

"Thread-32" prio= tid=0x00007f077c052800 nid=0x3b04 runnable [0x00007f06fec7d000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:)
at java.net.SocketInputStream.read(SocketInputStream.java:)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:)
at java.io.BufferedInputStream.read(BufferedInputStream.java:)
- locked <0x00000000d8ccf078> (a java.io.BufferedInputStream)
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:)
at org.apache.thrift.transport.TSaslTransport.readLength(TSaslTransport.java:)
at org.apache.thrift.transport.TSaslTransport.readFrame(TSaslTransport.java:)
at org.apache.thrift.transport.TSaslTransport.read(TSaslTransport.java:)
at org.apache.thrift.transport.TSaslClientTransport.read(TSaslClientTransport.java:)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:)
at org.apache.hive.service.cli.thrift.TCLIService$Client.recv_ExecuteStatement(TCLIService.java:)
at org.apache.hive.service.cli.thrift.TCLIService$Client.ExecuteStatement(TCLIService.java:)
at org.apache.hive.jdbc.HiveStatement.execute(HiveStatement.java:)
at org.apache.solr.handler.dataimport.JdbcDataSource$ResultSetIterator.<init>(JdbcDataSource.java:)
at org.apache.solr.handler.dataimport.JdbcDataSource.getData(JdbcDataSource.java:)
at org.apache.solr.handler.dataimport.JdbcDataSource.getData(JdbcDataSource.java:)
at org.apache.solr.handler.dataimport.SqlEntityProcessor.initQuery(SqlEntityProcessor.java:)
at org.apache.solr.handler.dataimport.SqlEntityProcessor.nextRow(SqlEntityProcessor.java:)
at org.apache.solr.handler.dataimport.EntityProcessorWrapper.nextRow(EntityProcessorWrapper.java:)
at org.apache.solr.handler.dataimport.DocBuilder.buildDocument(DocBuilder.java:)
at org.apache.solr.handler.dataimport.DocBuilder.buildDocument(DocBuilder.java:)
at org.apache.solr.handler.dataimport.DocBuilder.doDelta(DocBuilder.java:)
at org.apache.solr.handler.dataimport.DocBuilder.execute(DocBuilder.java:)
at org.apache.solr.handler.dataimport.DataImporter.doDeltaImport(DataImporter.java:)
at org.apache.solr.handler.dataimport.DataImporter.runCmd(DataImporter.java:)

  

扩展阅读

遇到这个问题以后想了解下jdbc的超时机制,所以google了一把,看到两篇文档对我很有帮助,文档链接在文章的最后。一篇是关于jdbc超时机制的,另一篇是关于socket的keepalive。

总结一下jdbc相关的timeout有以下几种:

Transaction Timeout,用来限制一个事务的执行时间。

Statement Timeout,限制一条查询的执行时间,设置方法:java.sql.Statement.setQueryTimeout(int timeout)。

Socket Timeout,又包含connection timeout和read/write timeout,限制建立连接的时间和等待读取或者等待写数据的时间。

OS level socket Timeout,这个其实是Linux系统环境下的Socket的KeepAlive机制。java的Socket类里有个setKeepAlive(boolean on)方法可能就是用来设置KeepAlive机制是否生效。

KeepAlive的作用:

之前一直不明白为什么很多系统都要自己实现一个心跳机制,比如微信,导致信令风暴啊什么的很多问题。看完KeepAlive的文章后才有这样的感觉,原来如此啊!

1,检查连接是否活着

KeepAlive可以侦测到一些原因造成的失效的socket连接,比如内核错误或者连接的进程强制退出,还比如虽然连接的机器和进程都正常,但是网络已经出现故障。这些情况下,TCP是不知道连接已经失效的。

考虑下面这种情况,A发送SYN给B发起连接,B回复一个ACK/SYN,A又发送ACK到B,完成TCP的三次握手,连接建立成功。这个时候如果B突然崩溃,没有发送任何消息给A告知其已经崩溃,A就会一直以为B还活着。如果A正在等待B发送过来的数据,那么就会一直在那傻等着,而B即使重启成功它也不知道之前和A有连接,所以A永远等不到B的数据。如果有KeepAlive的话,它就会定时的发送数据给B,B收到数据后找不到对应的连接就会回复一个reset信息,那么A收到reset信息以后就知道连接已经失效。

    _____                                                     _____
| | | |
| A | | B |
|_____| |_____|
^ ^
|--->--->--->-------------- SYN -------------->--->--->---|
|---<---<---<------------ SYN/ACK ------------<---<---<---|
|--->--->--->-------------- ACK -------------->--->--->---|
| |
| system crash ---> X
|
| system restart ---> ^
| |
|--->--->--->-------------- PSH -------------->--->--->---|
|---<---<---<-------------- RST --------------<---<---<---|
| | 2,防止连接长时间无数据传输而被断开
比如下图的情况,NAT会监控A和B之间的所有连接,如果连接长时间处于闲置状态就会被断开。KeepAlive定期的发送数据可以促使连接不会被断开。
    _____           _____                                     _____
| | | | | |
| A | | NAT | | B |
|_____| |_____| |_____|
^ ^ ^
|--->--->--->---|----------- SYN ------------->--->--->---|
|---<---<---<---|--------- SYN/ACK -----------<---<---<---|
|--->--->--->---|----------- ACK ------------->--->--->---|
| | |
| | <--- connection deleted from table |
| | |
|--->- PSH ->---| <--- invalid connection |
| | |

下午的时候还做了个小测试,在一台机器上运行一个SocketServer的程序,另外一台运行Socket程序去连接SocketServer,这个时候我并没有设置Socket的任何timeout。然后断开网线,发现Socket抛出ReadTimeout异常。当时觉得很奇怪,还以为是底层有KeepAlive呢。后来想想可能是操作系统侦测到网线被拔掉了吧O(∩_∩)O~。

参考文献

http://www.cubrid.org/blog/dev-platform/understanding-jdbc-internals-and-timeout-configuration/

http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/

利用DataImportHandler建索引时一直无法完成的更多相关文章

  1. [慢查优化]建索引时注意字段选择性 & 范围查询注意组合索引的字段顺序

    文章转自:http://www.cnblogs.com/zhengyun_ustc/p/slowquery2.html 写在前面的话: 之前曾说过"不要求每个人一定理解 联表查询(join/ ...

  2. java web轻量级开发面试教程读书笔记:建索引时我们需要权衡的因素

    场景一,数据表规模不大,就几千行,即使不建索引,查询语句的返回时间也不长,这时建索引的意义就不大.当然,若就几千行,索引所占的空间也不多,所以这种情况下,顶多属于"性价比"不高. ...

  3. oracle建索引的可选项

    oracle中建索引可能大家都会,但是建索引是有几个选项参数却很少有人关注,在某些特殊环境下,可能会非常有用,下面一一说明: 1.NOSORT,记录排序可选项. 默认情况下,在表中创建索引的时候,会对 ...

  4. Oracle使用并行建索引须要注意的问题

    建索引时.我们为了建索引快.会加上并行,加上并行之后.此列索引就会是并行了. 訪问有并行度的索引时,CBO可能可能会考虑并行运行.这可能会引发一些问题,如在server资源紧张的时候用并行会引起更加严 ...

  5. INDEX--创建索引和删除索引时的SCH_M锁

    最近有一个困惑,生产服务器上有一表索引建得乱七八糟,经过整理后需要新建几个索引,再删除几个索引,建立索引时使用联机(ONLINE=ON)创建,查看下服务器负载(磁盘和CPU压力均比较低的情况)后就选择 ...

  6. 索引时利用K-邻近算法过滤重复歌曲

    最近一直在做公司搜索的优化与维护,做完索引和搜索的分离之后,又有一个新需求,因为做的是歌曲方面的搜索,所以在数据库中有多个同歌名,同演唱者的的数据,这样在用户搜索的时候,会出来一大堆不同版本的歌曲,影 ...

  7. Mongodb 3 查询优化(语句优化、建索引)

    一.explain(),语句分析工具 MongoDB 3.0之后,explain的返回与使用方法与之前版本有了很大的变化,介于3.0之后的优秀特色和我们目前所使用给的是3.0.7版本,本文仅针对Mon ...

  8. Mysql索引分析:适合建索引?不适合建索引?【转】

    数据库建立索引常用的规则如下: 1.表的主键.外键必须有索引: 2.数据量超过300的表应该有索引: 3.经常与其他表进行连接的表,在连接字段上应该建立索引: 4.经常出现在Where子句中的字段,特 ...

  9. MySQL 分区建索引

    200 ? "200px" : this.width)!important;} --> 介绍 mysql分区后每个分区成了独立的文件,虽然从逻辑上还是一张表其实已经分成了多张 ...

随机推荐

  1. Scrapy框架使用—quotesbot 项目(学习记录一)

    一.Scrapy框架的安装及相关理论知识的学习可以参考:http://www.yiibai.com/scrapy/scrapy_environment.html 二.重点记录我学习使用scrapy框架 ...

  2. notepad++正则表达式替换字符串详解

    正则表达式是一个查询的字符串,它包含一般的字符和一些特殊的字符,特殊字符可以扩展查找字符串的能力,正则表达式在查找和替换字符串的作用不可忽视,它 能很好提高工作效率. EditPlus的查找,替换,文 ...

  3. CocoaPods 报错 [!] Error installing JSONModel

    pod install p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #34bd26 } span.s1 { } ...

  4. Chapter 2 Open Book——25

    "My name is Edward Cullen," he continued. "I didn't have a chance to introduce myself ...

  5. NodeJS学习指南

    七天学会NodeJS NodeJS基础 什么是NodeJS 有啥用处 如何安装 安装程序 编译安装 如何运行 权限问题 模块 require exports module 模块初始化 主模块 完整示例 ...

  6. 检索字符创 php

    strstr()可以返回匹配的值 echo strstr("localhost", "os");返回ost echo substr_count("gg ...

  7. ssh: scp命令

    scp 复制命令 Eg. -r /tmp/q1 root@[::]/home 1.命令格式: scp [参数] [原路径] [目标路径] 2.命令功能: scp是 secure copy的缩写, sc ...

  8. hdu_5585_Less Time, More profit(二分+最大权闭合图)

    题目链接:hdu_5585_Less Time, More profit 题意: 有n个工厂,每建一个工厂要花费vi,需要时间ti,然后有m个商店,每个商店需要在指定的k个工厂中进货,才能盈利,如果其 ...

  9. 如何在网页标题栏title加入logo图标?

    打开某一个网页会在浏览器的标签栏处显示该网页的标题和图标,当网页被添加到收藏夹或者书签中时也会出现网页的图标,怎么在网页title左边显示网页的logo图标呢? 方法一(被动式): 制作一个ico格式 ...

  10. Excel教程(10) - 逻辑运算符

    AND 用途:所有参数的逻辑值为真时返回 TRUE(真):只要有 一个参数的逻辑值为假,则返回 FALSE(假). 语法:AND(logical1,logical2,  ). 参数:Logical1, ...