symious opened a new pull request, #11239:
URL: https://github.com/apache/ozone/pull/11239

   ## What changes were proposed in this pull request?
   
   `ContainerProtocolCalls#getBlock` and `#readChunk` fail over between 
datanodes
   via `tryEachDatanode`. For each datanode, they call
   `XceiverClientSpi#sendCommand(request, validators)`. In `XceiverClientGrpc` 
this
   goes to `sendCommandWithRetry`, which again tries every datanode of the
   pipeline. As a result:
   
   - every datanode is contacted N times, so a single call can take
     `N × N × ozone.client.read.timeout` before failing, and a read can take
     `read.max.retries × N × N × read.timeout`;
   - the request built for datanode A (`datanodeUuid`, EC replica index) may be
     sent to datanode B.
   
   This PR makes `tryEachDatanode` the only failover layer for these two 
commands:
   
   - `XceiverClientSpi`
     - Add `sendCommand(request, validators, datanode)`, which sends the command
       to the given datanode only. The default implementation falls back to
       `sendCommand(request, validators)`, so Ratis and short-circuit clients 
are
       unchanged.
     - Add `getDatanodesInOrder(blockID, cmdType)`. The default implementation
       returns the datanodes in `Pipeline#getClosestNode` order, which is the
       current behavior of `tryEachDatanode`.
   - `XceiverClientGrpc`
     - Extract the single-datanode part of `sendCommandWithRetry` into
       `sendCommandToDatanode`: send, run validators, update the GetBlock
       datanode cache. Both the existing retry loop and the new
       `sendCommand(request, validators, datanode)` use it.
     - `getDatanodesInOrder` reuses `sortDatanodes`, so the datanode order
       (leader / cached GetBlock datanode first, non-IN_SERVICE last,
       topology-aware or shuffled) is the same as before.
   - `ContainerProtocolCalls`
     - `tryEachDatanode` iterates over `getDatanodesInOrder`.
     - The per-datanode GetBlock/ReadChunk calls use the new single-datanode
       `sendCommand`.
   
   Other commands (`listBlock`, `readSmallFile`, ...) still use the inner 
failover
   and are not affected.
   
   After this change, the worst case for a read is
   `read.max.retries × N × read.timeout`.
   
   Note: `getBlockFromDatanode` (used by `ozone debug replicas chunk-info`) now
   really queries only the given datanode. Before this change it could silently
   return the result from another datanode.
   
   ## What is the link to the Apache JIRA
   
   https://issues.apache.org/jira/browse/HDDS-16419
   
   ## How was this patch tested?
   
   - `TestXceiverClientGrpc`
     - `testGetBlockRetryAlNodes` / `testReadChunkRetryAllNodes` now assert that
       each datanode is contacted exactly once (previously N² calls), and that
       the request's `datanodeUuid` matches the datanode it is sent to.
     - New `testReadChunkRetryNextNodeOnShortRead`: a short read from the first
       datanode is retried on the next datanode.
     - Existing ordering tests (leader, topology, IN_SERVICE first, connection
       reuse after GetBlock) pass unchanged.
   - `TestChunkInputStream`, `TestBlockInputStream` pass.
   - Manually reproduced on a test cluster: with read.timeout=5s and 2
     unresponsive datanodes, the read failed after 60s before this change.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to