- OzoneClient は EndpointBase でInjectされている https://github.com/apache/ozone/blob/ozone-1.1.0/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java#L43-L44
- OMClientProducer に bind されている https://github.com/apache/ozone/blob/ozone-1.1.0/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java#L70
- OzoneClientFactory.getRpcClient(...) 内で omTransport を作っている
- まず
getClientProtocol(config, serviceId)
している https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java#L243 - これが
new RpcClient(config, serviceId)
している https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java#L154
OmTransport omTransport = OmTransportFactory.create(conf, ugi, omServiceId);
this.ozoneManagerClient = TracingUtil.createProxy(
new OzoneManagerProtocolClientSideTranslatorPB(omTransport,
clientId.toString()),
OzoneManagerProtocol.class, conf
)
OmTransportFactory.create(..)
はFactory pattern https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OmTransportFactory.java#L35- で、リフレクションを使って
new Hadoop30mTransport(...)
に渡る https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/Hadoop3OmTransportFactory.java#L33 - ここでRPC層の初期化が行われる https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/Hadoop3OmTransport.java#L59-L60
RPC.setProtocolEngine(OzoneConfiguration.of(conf),
OzoneManagerProtocolPB.class,
ProtobufRpcEngine.class);
this.omFailoverProxyProvider = new OMFailoverProxyProvider(conf, ugi,
omServiceId);
...
this.rpcProxy = createRetryProxy(omFailoverProxyProvider, maxFailovers);
-
RPC.setProtocolEngine(..)
は OzoneManagerProtocolPB に対する RpcEngine を ProtobufRpcEngine.class でグローバルに設定する -
omFailoverProxyProvider
は後で使う -
createRetryProxy(..)
はOMFailoverProxyProvider
を getProxy() したもの に RetryInvocationHandler をかぶせているだけ -
このときに OmFailoverProxyProvider#createOMProxy() の中で RPC.getProtocolProxy(...).getProxy() されている
-
RPC.getProtocolProxy(...)の中で getProtocolEngine(protocol, conf) しているところがあって、その直前で ProtobufRpcEngineをセットしているので、このときは ProtobufRpcEngine が返ってくる、それに対してい .getProxy() するので、そこで Invokerが作られる。
-
omFailoverProxyProvider を持った RetryInvocationHandler がこの中で newInstance されていて、これは RpcInvocationHandler を継承している
-
実際の Retry.create(...) はここ→ https://github.com/apache/hadoop/blob/rel/release-3.2.2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/retry/RetryProxy.java#L56-L63
-
これで
Hadoop30mTransport#rpcProxy
が初期化されるのでnew RpcClient(..)
の中まで戻る -
this.ozoneManagerClient = TracingUtil.createProxy(...)
では、omTransport
を使ってOzoneManagerProtocolClientSideTranslatorPB
を処理するProxyを作る。 -
OzoneManagerProtocolClientSideTranlatorPBが実質的にプロトコルを処理する ozoneManagerClient になる
-
new OzoneClient(...)
まで戻ると、そのあとnew ObjectStore(conf, proxy)
している https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java#L88 -
この ObjectStore も
proxy
をメンバに持っている https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java#L71
ここまでが初期化
PUT
だとgetBucket(..)
が最初のOMへのアクセスになる https://github.com/apache/ozone/blob/ozone-1.1.0/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java#L190getBucket
の中でclient.getObjectStore()
を呼ぶ https://github.com/apache/ozone/blob/ozone-1.1.0/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java#L68getS3Bucket(..) -> getVolume(..) -> proxy.getVolumeDetails(..)
と呼び出している- この proxy は
OzoneClient#getVolumeDetails(..)
につながっていて ozoneManagerClient.getVolumeInfo(..)
を呼んでいる https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java#L315- その先で
OzoneManagerProtocolClientSideTranslatorPB#submitRequest(..)
を呼んでいる https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java#L338 - これは細かいことを省くと
Hadoop30mTransport#submitRequest(..)
になっている https://github.com/apache/ozone/blob/f2406c4b4eb2b1295d06ec379cfe684ed9a16637/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/Hadoop3OmTransport.java#L77 - で、ここで
rpcProxy.submitRequest(..)
が呼ばれる・・・ - ここから先はリフレクションを使っていて追えないので、実際のスタックトレースから追う
==> /opt/hadoop/logs/ozone-ozone-s3g-hostname.example.log <==
2021-06-21 19:22:31,664 [qtp1516500233-515060] WARN org.apache.hadoop.net.NetUtils: Unable to wrap exception of type class org.apache.hadoop.ipc.RpcException: it has no (Str
ing) constructor
java.lang.NoSuchMethodException: org.apache.hadoop.ipc.RpcException.<init>(java.lang.String)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)
at org.apache.hadoop.net.NetUtils.wrapWithMessage(NetUtils.java:835)
at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:811)
at org.apache.hadoop.ipc.Client.getRpcResponse(Client.java:1566)
at org.apache.hadoop.ipc.Client.call(Client.java:1508)
at org.apache.hadoop.ipc.Client.call(Client.java:1405)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:233)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:118)
at com.sun.proxy.$Proxy86.submitRequest(Unknown Source)
at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:422)
at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invokeMethod(RetryInvocationHandler.java:165)
at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invoke(RetryInvocationHandler.java:157)
at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invokeOnce(RetryInvocationHandler.java:95)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:359)
at com.sun.proxy.$Proxy86.submitRequest(Unknown Source)
at org.apache.hadoop.ozone.om.protocolPB.Hadoop3OmTransport.submitRequest(Hadoop3OmTransport.java:80)
at org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB.submitRequest(OzoneManagerProtocolClientSideTranslatorPB.java:220)
at org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB.openKey(OzoneManagerProtocolClientSideTranslatorPB.java:595)
at org.apache.hadoop.ozone.client.rpc.RpcClient.createKey(RpcClient.java:718)
at org.apache.hadoop.ozone.client.OzoneBucket.createKey(OzoneBucket.java:491)
at org.apache.hadoop.ozone.s3.endpoint.ObjectEndpoint.put(ObjectEndpoint.java:192)
- RetryProxy を挟んでいて、具体的には
RetryInvocationHandler
をInvocationHandlerに持っている - まず そこの
invoke()
が呼ばれることがわかる - この中で
invokeMethod(method, args)
がよばれて、そこでproxyDescriptor.getProxy()
が走る https://github.com/apache/hadoop/blob/rel/release-3.2.2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/retry/RetryInvocationHandler.java#L422 proxyDescriptor.getProxy()
はOzoneManagerProtocolPB
なので、RetryInvocationHandler
内で再度リフレクションが走って ProtobufRpcEngine#invoke() が呼ばれる https://github.com/apache/hadoop/blob/rel/release-3.2.2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/ProtobufRpcEngine.java#L233-L235Client#call()
から https://github.com/apache/hadoop/blob/rel/release-3.2.2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java#L1405-L1406Client#getRpcResponse()
で非同期にExceptionを受け取る https://github.com/apache/hadoop/blob/7a3bc90b05f257c8ace2f76d74264906f0f7a932/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java#L1545
実際にRpcExceptionを投げていたのは
Caused by: org.apache.hadoop.ipc.RpcException: RPC response exceeds maximum data length
at org.apache.hadoop.ipc.Client$IpcStreams.readResponse(Client.java:1894)
at org.apache.hadoop.ipc.Client$Connection.receiveRpcResponse(Client.java:1191)
at org.apache.hadoop.ipc.Client$Connection.run(Client.java:1087)
のスタックから推察するに Client.java のここ。 Client
がThreadを継承しているこおから非同期RPCのスレッドプールがあって、その中で例外を投げるとこういう風になるんじゃないかと踏んでいる。
if (maxResponseLength > 0 && length > maxResponseLength) {
throw new RpcException("RPC response exceeds maximum data length");
}
この maxResponseLength
の由来を追うのが次
- これはConnectionを初期化するときに remoteId.conf からくる https://github.com/apache/hadoop/blob/rel/release-3.2.2/hadoop-common-
- ConnectionはClient#getConnectionでnewしている
- Client#getConnectionは Client#call の中で実行している→この call に remoteId が渡されている
- ProtobufRpcEngine.Invoker#remoteId がそれに相当する。で、 Invoker#invoke 内でcall()を呼んでいてそれが渡されている
- Invokerは ProtobufRpcEngine#getProxy() から呼ばれている
- ということで、大元は
OzoneClientProducer#ozoneConfiguration
から来ている。
やっぱちゃんと渡ってこないとおかしい感じするよな・・・