phoenix查询异常的问题(PhoenixIOException)

phoenix查询异常的问题org.apache.phoenix.exception.PhoenixIOException 系统找不到指定的路径


Window环境下,当出现如下问题的解决办法

exception is org.apache.phoenix.exception.PhoenixIOExceptionorg.apache.phoenix.exception.PhoenixIOException系统找不到指定的路径。

    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104)

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)

    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)

    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637)

    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666)

    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674)

    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:714)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    at java.lang.reflect.Method.invoke(Method.java:606)

    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)

    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)

    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)

    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)

    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)

    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)

    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)

    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)

    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)

    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:154)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:92)

    at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:106)

    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)

    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)

    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)

    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)

    at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:173)

    at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)

    at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:274)

    at com.caucho.server.port.TcpConnection.run(TcpConnection.java:511)

    at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:520)

    at com.caucho.util.ThreadPool.run(ThreadPool.java:442)

    at java.lang.Thread.run(Thread.java:745)

Caused by: org.apache.phoenix.exception.PhoenixIOExceptionorg.apache.phoenix.exception.PhoenixIOException系统找不到指定的路径。

    at org.apache.phoenix.util.ServerUtil.parseServerException(ServerUtil.java:108)

    at org.apache.phoenix.iterate.BaseResultIterators.getIterators(BaseResultIterators.java:558)

    at org.apache.phoenix.iterate.MergeSortResultIterator.getIterators(MergeSortResultIterator.java:48)

    at org.apache.phoenix.iterate.MergeSortResultIterator.minIterator(MergeSortResultIterator.java:84)

    at org.apache.phoenix.iterate.MergeSortResultIterator.next(MergeSortResultIterator.java:111)

    at org.apache.phoenix.iterate.DelegateResultIterator.next(DelegateResultIterator.java:44)

    at org.apache.phoenix.iterate.LimitingResultIterator.next(LimitingResultIterator.java:47)

    at org.apache.phoenix.jdbc.PhoenixResultSet.next(PhoenixResultSet.java:771)

    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:91)

    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:1)

    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:649)

    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)

    ... 37 more

Caused by: java.util.concurrent.ExecutionExceptionorg.apache.phoenix.exception.PhoenixIOException系统找不到指定的路径。

    at java.util.concurrent.FutureTask.report(FutureTask.java:122)

    at java.util.concurrent.FutureTask.get(FutureTask.java:202)

    at org.apache.phoenix.iterate.BaseResultIterators.getIterators(BaseResultIterators.java:554)

    ... 47 more

Caused by: org.apache.phoenix.exception.PhoenixIOException系统找不到指定的路径。

    at org.apache.phoenix.util.ServerUtil.parseServerException(ServerUtil.java:108)

    at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:151)

    at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:86)

    at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:64)

    at org.apache.phoenix.iterate.SpoolingResultIterator$SpoolingResultIteratorFactory.newIterator(SpoolingResultIterator.java:81)

    at org.apache.phoenix.iterate.ChunkedResultIterator.(ChunkedResultIterator.java:92)

    at org.apache.phoenix.iterate.ChunkedResultIterator.(ChunkedResultIterator.java:47)

    at org.apache.phoenix.iterate.ChunkedResultIterator$ChunkedResultIteratorFactory.newIterator(ChunkedResultIterator.java:72)

    at org.apache.phoenix.iterate.ParallelIterators$1.call(ParallelIterators.java:109)

    at org.apache.phoenix.iterate.ParallelIterators$1.call(ParallelIterators.java:100)

    at java.util.concurrent.FutureTask.run(FutureTask.java:262)

    at org.apache.phoenix.job.JobManager$InstrumentedJobFutureTask.run(JobManager.java:183)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

    ... 1 more

Caused by: java.io.IOException系统找不到指定的路径。

    at java.io.WinNTFileSystem.createFileExclusively(Native Method)

    at java.io.File.createTempFile(File.java:2001)

    at org.apache.commons.io.output.DeferredFileOutputStream.thresholdReached(DeferredFileOutputStream.java:176)

    at org.apache.phoenix.iterate.SpoolingResultIterator$1.thresholdReached(SpoolingResultIterator.java:118)

    at org.apache.commons.io.output.ThresholdingOutputStream.checkThreshold(ThresholdingOutputStream.java:224)

    at org.apache.commons.io.output.ThresholdingOutputStream.write(ThresholdingOutputStream.java:92)

    at java.io.DataOutputStream.writeByte(DataOutputStream.java:153)

    at org.apache.hadoop.io.WritableUtils.writeVLong(WritableUtils.java:289)

    at org.apache.hadoop.io.WritableUtils.writeVInt(WritableUtils.java:253)

    at org.apache.phoenix.util.TupleUtil.write(TupleUtil.java:149)

    at org.apache.phoenix.iterate.SpoolingResultIterator.(SpoolingResultIterator.java:129)

    ... 13 more



原理分析:


当通过sql语句以phoenix方式查询hbase数据的时候,hbase这时候有可能会通过多线程的方式并发查询结果,查询完成后,系统会将这些结果返回给客户端,客户端在对这些结果合并,输出给用户。例如如果查询的sql语句增加了 limit 10, hbase后台服务查询的数据并发线程是50的话,那么实际上每个线程都会返回10条记录给客户端,客户端将收到50*10=500条记录,然后在排序,取出前10条。


这个异常发生的时序如下:(假设现在有50个并发线程查询,每个线程返回10条记录)

1,phoenix查询后,会通过phoenix-core/src/main/java/org/apache/phoenix/iterate/SpoolingResultIterator.java 类构造一个返回的对象,在这个类的构造方法中,会有如下代码



通过代码分析: 在构造这个对象的时候需要分配一个内存空间  thresholdBytes,那这个值是从哪里来的呢(通过分析发现这个是来自配置文件 ,这个值默认是20M)


同时系统分配内存的时候,会返回20M的空间(但是也不一定,当usedMemoryBytes很小的时候,那么他就不会返回20M了,而是返回一个小的实际可用的内存值,同时分配完这块内存后,系统会增加usedMemoryBytes,正常增加20M),代码如下




接下来回到上面的SpoolingResultIterator.java类,这个类得到了分配的内存的size后调用了

DeferredFileOutputStream,这个类接收了一个参数size, 这个类是干什么的呢,它的意思是输出流在内存,当超过阈值size的时候,需要把这个流写入到磁盘,所以后面还有参数是File对象,主要就是为了写入磁盘使用的。我们这个问题就出现在这里,当写入磁盘的时候,由于是window系统,无法在/tmp创建一个临时文件,所以出现IOException的问题。

因为50个线程会生成50个SpoolingResultIterator.java对象不断的去分配20M的内存,最终会导致usedMemoryBytes数字一直增加,当增加到一定阈值的时候 (当前JVM -Xmx * 0.15 ),系统就无法分配别的内存了,这时候肯定需要磁盘来作为DeferedFileOutputStream了,这时候就出现上面的错误了。 那么这个0.15是从哪里来的呢,也是来自config : phoenix.query.maxGlobalMemoryPercentage  默认值是15,也就是百分比是0.15了。换句话说phoenix允许usedMemeory数量是 -Xmx * 0.15 


如何解决这个问题:

方法1: 不改任何配置文件,如果50个并发的话,每个20M,那么为了不让系统通过Disk输出,一直保持在内存内,那么它需要50*20=1G内存。 然后在用 1G/0.15 = 6.6G ,那么你把JVM的 -Xmx配置成8个G肯定就没有问题了

方法2: 因为无法修改服务端你的50个并发的设置,所以我们可以通过配置参数减少20M,同时增加maxGlobalMemoryPercentage 方式来保证也在内存中使用,例如配置phoenix.query.spoolThresholdBytes=5M ,phoenix.query.maxGlobalMemoryPercentage = 40 的话,你只需要JVM的-Xmx最大是= 50*5/0.4=625M 如果配置超过这个大小,也会在内存计算,所以不会用到磁盘,也不会报错

方法3: 什么也不改,把系统部署到Linux上,保证存储/tmp目录,让phoenix在磁盘运算,也不会报错,但是这样性能肯定会有影响了


如果用方法2,需要在客户端你的hbase-site.xml里面配置如下内容:


	phoenix.query.maxGlobalMemoryPercentage
	50



	phoenix.query.spoolThresholdBytes
	5388608

你可能感兴趣的:(大数据)