Проблема SocketTimeoutException от клиента HBase

мы работаем над сценарием, в котором нам нужно проверить существование записи перед вставкой. Если запись уже существует, мы не вставляем ее снова. Мы делаем партиями. Сначала мы создаем пакет Get, чтобы увидеть существование записей, которые мы хотим вставить. Эта проблема не возникает, когда размер таблицы меньше, а также она очень прерывистая. каков рекомендуемый размер партии для Get. И каков наилучший подход для проверки существования записей перед вставкой?? Ценю ваши ответы..

вот трассировка стека..

java.util.concurrent.ExecutionException: java.net.SocketTimeoutException: Call to b16-pf-dv-093.abc.com/10.106.8.103:60020 failed on socket timeout exception: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222) 
        at java.util.concurrent.FutureTask.get(FutureTask.java:83) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1604) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1456) 
        at org.apache.hadoop.hbase.client.HTable.batch(HTable.java:757) 
        at org.apache.hadoop.hbase.client.HTable.get(HTable.java:726) 
        at org.apache.hadoop.hbase.client.HTablePool$PooledHTable.get(HTablePool.java:367) 
        at com.abc.psp.core.metering.util.HBaseClient.get(HBaseClient.java:263) 
        at com.abc.psp.core.metering.dao.MeteringHBaseDAOImpl.addMeteredRecords(MeteringHBaseDAOImpl.java:374) 
        at com.abc.psp.core.metering.dao.MeteringHBaseDAOImpl.addMeteredRecords(MeteringHBaseDAOImpl.java:342) 
        at HBaseTest.main(HBaseTest.java:32) 
Caused by: java.net.SocketTimeoutException: Call to b16-pf-dv-093.abc.com/10.106.8.103:60020 failed on socket timeout exception: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at org.apache.hadoop.hbase.ipc.HBaseClient.wrapException(HBaseClient.java:1026) 
        at org.apache.hadoop.hbase.ipc.HBaseClient.call(HBaseClient.java:999) 
        at org.apache.hadoop.hbase.ipc.WritableRpcEngine$Invoker.invoke(WritableRpcEngine.java:86) 
        at $Proxy6.multi(Unknown Source) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.call(HConnectionManager.java:1433) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.call(HConnectionManager.java:1431) 
        at org.apache.hadoop.hbase.client.ServerCallable.withoutRetries(ServerCallable.java:215) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.call(HConnectionManager.java:1440) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.call(HConnectionManager.java:1428) 
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
        at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
        at java.lang.Thread.run(Thread.java:662) 
Caused by: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at org.apache.hadoop.net.SocketIOWithTimeout.doIO(SocketIOWithTimeout.java:164) 
        at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:155) 
        at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:128) 
        at java.io.FilterInputStream.read(FilterInputStream.java:116) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection$PingInputStream.read(HBaseClient.java:373) 
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) 
        at java.io.BufferedInputStream.read(BufferedInputStream.java:237) 
        at java.io.DataInputStream.readInt(DataInputStream.java:370) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection.receiveResponse(HBaseClient.java:646) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection.run(HBaseClient.java:580)

2 ответов


вы получаете эту ошибку, потому что время, затрачиваемое вашим gets, больше, чем допустимое по умолчанию время, которое клиентские приложения HBase могут принимать для удаленного вызова тайм-аута, который 60 секунд. Когда ваша таблица большая (что означает, что у вас есть больше данных для извлечения), это займет время. Вы можете увеличить это значение, установив значение в HBase.протокол RPC.ожидания к некоторому более высокому значению в вашем в HBase-сайте.в XML.

что такое рекомендуемый размер партии для Get?

зависит от вашего дизайна, конфигурации, спецификаций, данных и шаблона доступа.

каков наилучший подход для проверки существования записей перед вставкой?

когда вы хотите проверить что-то, проверка является единственным вариантом. Было бы полезно, если бы вы могли разработать свой вариант использования немного больше. Это поможет мне сделать правильное предложение.


решение, представленное здесь, не является 100% правильным. Я столкнулся с socketTimeOut как при чтении, так и при записи с высокой нагрузкой. Растет в HBase.протокол RPC.timeout не является решением до тех пор, пока сканирование или запись на сервере hbase не будут очень большими.

вот моя проблема:

Я попытался сканировать строки, которые были возвращены hbase за несколько миллисекунд. Все было нормально, пока я не увеличил потоки параллельного сканирования с 10 до 50. Таким образом, я начал испытывать socketTimeoutException (то же исключение, что и в этом потоке), которое является препятствием для масштабирования чтения или записи hbase из одного процесса.

чтобы добраться до точного решения, вам сначала нужно понять причину.

причины для socketTimeout

a. Чтение или запись возвращаются с сервера hbase медленно

b. Клиент не может подключиться к серверу и истекло время ожидания. Нити заложенность?

Если вы испытываете "a", то увеличение hbase.протокол RPC.тайм-аут может быть вашим решением, но все же вы, скорее всего, окажетесь на "b".

Я заметил, что клиент hbase по умолчанию создает только одно соединение на regionServer. Чтобы проверить, выполните эту команду от клиента, где выполняются чтения в hbase. Убедитесь, что нагрузка работает.

netstat -an | grep 60020 | grep EST

к моему удивлению, для каждого regionServer, процесс сделал только одно соединение. Это объясняло тайм-ауты. Только одно соединение / сокет? Кажется, что это поведение клиента hbase по умолчанию. Еще не знаю почему?

решение:

добавьте эти два свойства в HBase conf в клиенте и перезапустите клиент

<property>
   <name>hbase.client.ipc.pool.type</name>
   <value>RoundRobinPool</value>
</property>
<property>
   <name>hbase.client.ipc.pool.size</name>
   <value>10</value>
</property>

это создало 10 сокетов на каждом regionServer от каждого клиента. С этим изменением вы должны увидеть значительное улучшение на стороне клиента. Я не испытывал socketTimeOutException, с этой перемены.