[
https://issues.apache.org/jira/browse/HBASE-13851?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14575524#comment-14575524
]
Enis Soztutar edited comment on HBASE-13851 at 6/6/15 2:24 AM:
---------------------------------------------------------------
Here is an explanation of what is happening for the brave souls:
The RpcClientImpl just hangs in close() after interrupting every Connection
thread that is running.
We have the Connection thread and the CallSender thread per RS. CallSender is
only started if we are using specifiThreadForWriting (enabled for replica
reads). The CallSender thread is started in Connection constructor, while the
Connection thread itself is started only after the setupIOStreams() is
successful. setupIOStreams() is called only in the case of a call being written.
RPCClientImpl keeps a map of Connection objects. A new Rpc Call will create a
new Connection object and add it to the map if needed. On RpcClient.close() it
interrupts all Connections and waits until all Connections in the map are
removed. Normally, the Connection thread after getting an interruption will
call markClosed() and then the Thread run loop will end which as a last
operation will call close(). Connection.close() removes the Connection from the
RpcClient's connections map.
If a replica RPC is performed, a Connection object is constructed, and added to
the map. Normally the Rpc Call is handled by the RpcSender thread which is
already running, and it will setupIOStreams() and depending on whether an
exception or not, it will either start the Connection thread or call
Connection.close() which will remove the Connection from the map.
In a rare case, a new Connection can be created, but before CallSender sends
the RPC call and for that sets up IO streams and starts the Connection thread,
the RPC may be cancelled if another replica responded first. Previously we were
not canceling the RPC, but after HBASE-12668, the cancelation is happening
which will cause the Connection thread to not start at all if there are no more
RPCs coming. In this case, since there is no Connection thread running, the
RpcClientImpl.close() will not be able to interrupt the thread (since it is not
running), and Connection.close() will never be called.
was (Author: enis):
Here is an explanation of what is happening for the brave souls:
The RpcClientImpl just hangs in close() after interrupting every Connection
thread that is running.
We have the Connection thread and the CallSender thread per RS. CallSender is
only started if we are using specifiThreadForWriting (enabled for replica
reads). The CallSender thread is started in Connection constructor, while the
Connection thread itself is started only after the setupIOStreams() is
successful. setupIOStreams() is called only in the case of a call being written.
RPCClientImpl keeps a map of Connection objects. A new Rpc Call will create a
new Connection object and add it to the map if needed. On RpcClient.close() it
interrupts all Connections and waits until all Connections in the map are
removed. Normally, the Connection thread after getting an interruption will
call markClosed() and then the Thread run loop will end which as a last
operation will call close(). Connection.close() removes the Connection from the
RpcClient's connections map.
If a replica RPC is performed, a Connection object is constructed, and added to
the map. Normally the Rpc Call is handled by the RpcSender thread which is
already running, and it will setupIOStreams() and depending on whether an
exception or not, it will either start the Connection thread or call
Connection.close() which will remove the Connection from the map.
In a rare case, a new Connection can be created, but before CallSender sends
the RPC call and for that sets up IO streams and starts the Connection thread,
the RPC may be cancelled if another replica responded first. Previously we were
not canceling the RPC, but after HBASE-12668, the cancelation is happening
which will cause the Connection thread to not start at all if there are no more
RPCs coming. In this case, since there is no Connection thread running, the
RpcClientImpl.close() will not be able to interrupt the thread (since it is not
running), and Connection.close() will never be called.
> RpcClientImpl.close() can hang with cancelled replica RPCs
> ----------------------------------------------------------
>
> Key: HBASE-13851
> URL: https://issues.apache.org/jira/browse/HBASE-13851
> Project: HBase
> Issue Type: Bug
> Reporter: Enis Soztutar
> Assignee: Enis Soztutar
> Fix For: 2.0.0, 1.2.0, 1.1.1
>
>
> We have seen the clients hanging in running the test
> {{IntegrationTestRegionReplicaPerf}} in 1.1 code base during the test.The
> jstack gives:
> {code}
> "IPC Client (1344340481) connection to
> os-enis-dal-test-jun-4-1.openstacklocal/172.22.80.25:16020 from root -
> writer" daemon prio=10 tid=0x00007f3891b29800 nid=0x7345 waiting on condition
> [0x00007f3865647000]
> java.lang.Thread.State: WAITING (parking)
> at sun.misc.Unsafe.park(Native Method)
> - parking to wait for <0x000000070d54a240> (a
> java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
> at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
> at
> java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
> at
> java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:374)
> at
> org.apache.hadoop.hbase.ipc.RpcClientImpl$Connection$CallSender.run(RpcClientImpl.java:253)
> "TestClient-3" prio=10 tid=0x00007f3892660800 nid=0x63b0 waiting on condition
> [0x00007f386ecdd000]
> java.lang.Thread.State: TIMED_WAITING (sleeping)
> at java.lang.Thread.sleep(Native Method)
> at
> org.apache.hadoop.hbase.ipc.RpcClientImpl.close(RpcClientImpl.java:1139)
> at
> org.apache.hadoop.hbase.client.ConnectionManager$HConnectionImplementation.internalClose(ConnectionManager.java:2371)
> at
> org.apache.hadoop.hbase.client.ConnectionManager$HConnectionImplementation.close(ConnectionManager.java:2384)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation$Test.testTakedown(PerformanceEvaluation.java:1036)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation$RandomReadTest.testTakedown(PerformanceEvaluation.java:1351)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation$Test.test(PerformanceEvaluation.java:1055)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation.runOneClient(PerformanceEvaluation.java:1612)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation$1.call(PerformanceEvaluation.java:410)
> at
> org.apache.hadoop.hbase.PerformanceEvaluation$1.call(PerformanceEvaluation.java:405)
> at java.util.concurrent.FutureTask.run(FutureTask.java:262)
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
> at java.lang.Thread.run(Thread.java:745)
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)