4444
4545/**
4646 * HTTP/2 protocol client invoker, supporting both h2 and http2c.
47- *
48- * <p>Each {@link #send(Request)} entry signals the underlying {@link Http2cRpcClient} that
49- * it is being used (drives the idle-eviction heuristic) and reports success / failure to
50- * drive the consecutive-failure counter that flips the client to unavailable on sustained
51- * backend outages.</p>
5247 */
5348public class Http2ConsumerInvoker <T > extends AbstractConsumerInvoker <T > {
5449
@@ -72,31 +67,20 @@ public Http2ConsumerInvoker(Http2cRpcClient client, ConsumerConfig<T> config,
7267 @ Override
7368 public Response send (Request request ) throws Exception {
7469 Http2cRpcClient http2cRpcClient = (Http2cRpcClient ) client ;
75- // Mark "used" before any work so even a failed request keeps the idle-eviction timer
76- // accurate (a failing client is still actively used and must not be reaped as orphan).
77- http2cRpcClient .markUsed ();
7870
7971 int requestTimeout = config .getBackendConfig ().getRequestTimeout ();
8072 SimpleHttpRequest simpleHttpRequest ;
8173 try {
8274 simpleHttpRequest = buildRequest (request , requestTimeout );
8375 } catch (Exception ex ) {
84- http2cRpcClient .markFailure ();
8576 return RpcUtils .newResponse (request , null , ex );
8677 }
8778
8879 try {
8980 SimpleHttpResponse simpleHttpResponse = execute (request , requestTimeout ,
9081 simpleHttpRequest , http2cRpcClient );
91- Response response = handleResponse (request , simpleHttpResponse );
92- if (response .getException () == null ) {
93- http2cRpcClient .markSuccess ();
94- } else {
95- http2cRpcClient .markFailure ();
96- }
97- return response ;
82+ return handleResponse (request , simpleHttpResponse );
9883 } catch (Exception e ) {
99- http2cRpcClient .markFailure ();
10084 return RpcUtils .newResponse (request , null , e );
10185 }
10286
@@ -164,42 +148,56 @@ private SimpleHttpResponse execute(Request request, int requestTimeout,
164148 SimpleHttpRequest simpleHttpRequest , Http2cRpcClient http2cRpcClient ) throws Exception {
165149 CloseableHttpAsyncClient httpAsyncClient = http2cRpcClient .getHttpAsyncClient ();
166150 Future <SimpleHttpResponse > httpResponseFuture = httpAsyncClient .execute (simpleHttpRequest ,
167- new FutureCallback <SimpleHttpResponse >() {
168- @ Override
169- public void completed (SimpleHttpResponse result ) {
170- if (logger .isDebugEnabled ()) {
171- logger .debug (result .getBodyText ());
172- }
173- }
174-
175- @ Override
176- public void failed (Exception ex ) {
177- String msg = String
178- .format ("request has exception > %s ms, service=%s, "
179- + "method=%s, remoteAddr=%s, exception=%s" ,
180- requestTimeout ,
181- request .getInvocation ().getRpcServiceName (),
182- request .getInvocation ().getRpcMethodName (),
183- request .getMeta ().getRemoteAddress (),
184- ex .getMessage ());
185- logger .error (msg );
186- }
187-
188- @ Override
189- public void cancelled () {
190- String msg = String
191- .format ("request cancel > %s ms, service=%s, "
192- + "method=%s, remoteAddr=%s" ,
193- requestTimeout ,
194- request .getInvocation ().getRpcServiceName (),
195- request .getInvocation ().getRpcMethodName (),
196- request .getMeta ().getRemoteAddress ());
197- logger .error (msg );
198- }
199- });
151+ newResponseCallback (request , requestTimeout ));
200152 return httpResponseFuture .get (requestTimeout , TimeUnit .MILLISECONDS );
201153 }
202154
155+ /**
156+ * Build the {@link FutureCallback} used to log the asynchronous request outcome. Extracted
157+ * (package-private) from {@link #execute} so the completed / failed / cancelled logging
158+ * branches can be unit-tested directly — the convenience {@code execute(SimpleHttpRequest,
159+ * FutureCallback)} on {@link CloseableHttpAsyncClient} is {@code final} and cannot be stubbed.
160+ *
161+ * @param request the originating TRPC request (used only for log context)
162+ * @param requestTimeout the request timeout in milliseconds (used only for log context)
163+ * @return a logging-only callback; it never mutates request/response state
164+ */
165+ FutureCallback <SimpleHttpResponse > newResponseCallback (Request request , int requestTimeout ) {
166+ return new FutureCallback <SimpleHttpResponse >() {
167+ @ Override
168+ public void completed (SimpleHttpResponse result ) {
169+ if (logger .isDebugEnabled ()) {
170+ logger .debug (result .getBodyText ());
171+ }
172+ }
173+
174+ @ Override
175+ public void failed (Exception ex ) {
176+ String msg = String
177+ .format ("request has exception > %s ms, service=%s, "
178+ + "method=%s, remoteAddr=%s, exception=%s" ,
179+ requestTimeout ,
180+ request .getInvocation ().getRpcServiceName (),
181+ request .getInvocation ().getRpcMethodName (),
182+ request .getMeta ().getRemoteAddress (),
183+ ex .getMessage ());
184+ logger .error (msg );
185+ }
186+
187+ @ Override
188+ public void cancelled () {
189+ String msg = String
190+ .format ("request cancel > %s ms, service=%s, "
191+ + "method=%s, remoteAddr=%s" ,
192+ requestTimeout ,
193+ request .getInvocation ().getRpcServiceName (),
194+ request .getInvocation ().getRpcMethodName (),
195+ request .getMeta ().getRemoteAddress ());
196+ logger .error (msg );
197+ }
198+ };
199+ }
200+
203201 /**
204202 * Wrap the TRPC request into an HTTP request.
205203 *
0 commit comments