Skip to content

SOLR-18312: introduce dedicated thread pool executor for httpClientBu… - #4655

Open
renatoh wants to merge 8 commits into
apache:mainfrom
renatoh:SOLR-18312-fix-Thread-Pool-Starvation-in-HttpJdkSolrClient
Open

SOLR-18312: introduce dedicated thread pool executor for httpClientBu…#4655
renatoh wants to merge 8 commits into
apache:mainfrom
renatoh:SOLR-18312-fix-Thread-Pool-Starvation-in-HttpJdkSolrClient

Conversation

@renatoh

@renatoh renatoh commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (SOLR-18312) updates HttpJdkSolrClient to use a dedicated executor for the JDK HttpClient, aiming to prevent deadlocks when request bodies are streamed (producer) while the JDK client consumes them (consumer), particularly under HTTP/1.1 with concurrent requests.

Changes:

  • Introduce a separate httpClientExecutor that is always owned and shut down by HttpJdkSolrClient, instead of reusing the request-body streaming executor.
  • Add a concurrency regression test that issues multiple concurrent JsonQueryRequest calls with large streamed bodies while forcing HTTP/1.1.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java Adds a dedicated executor for the underlying JDK HttpClient and ensures it is shut down on close.
solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java Adds a concurrent, streamed-body test intended to catch deadlocks under HTTP/1.1.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java Outdated
Comment thread solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java Outdated

@dsmiley dsmiley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be more natural for the builder/configured executor to be for the httpClient usage itself, just as the jetty one.

@dsmiley

dsmiley commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

I pushed an improvement to defer the use of the executor for body thread pushing to only start when it's requested (by the supplier). Maybe in practice won't be notice but I like the code for it much better now. CC @serhiy-bzhezytskyy

@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor

@dsmiley the deferral does more than tidy the code — it removes the leak by construction for one whole class of failure. I measured it with a counting executor on a refused connection: before e534b380e one body task is submitted and then has to be released; after it, zero (expected:<0> but was:<1> against the previous commit). So the original SOLR-17707 guard now only covers "body requested, then the connection dropped", which is the narrower case it should have been.

Two things I checked while I was in here, both fine:

  • the mechanism sentence still holds. I mutated the fix on main to keep only cancel(true) and the SOLR-17707 test fails with content-writing thread leaked, still blocked after failure — so close(sink) is still load-bearing, and moving the comment along with the code was right.
  • contentWritingSink is assigned before contentWritingFuture, so a releaseContentWriting() arriving between them finds a null future and an already-closed sink. Over 200 runs that is 200 writers exiting on IOException with the pool fully drained — log noise, not a leak. Not worth a change.

The one thing missing is a test for the new property. I have the one above if you want it, against this branch or as a follow-up.

@dsmiley

dsmiley commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Thanks for the review Serhiy. testStuckContentWritingThreadIsReleasedOnFailure that you added previously is good enough IMO. I just pushed a change to switch from volatile to synchronized, which avoids the sequence issue you pointed out -- thanks for that.

@renatoh

renatoh commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@dsmiley I resolved all the Copilot remarks. As far as I can see everything has been resolved, or is there anything left before this PR can be merged?

@dsmiley dsmiley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the change (that I introduced RE executor initialization) results in no enforced cap/limit on threads. I didn't check if there's one at the JDK HttpClient level. If there's no limit, then it's worth a major-changes-since adoc file note. We should probably have a bit of javadoc somewhere to communicate whatever limit may or may not exist so at least users know. If there's no limit, IMO it's fine. It's straight-forward for a user to enforce via a semaphore if they wish.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 14, 2026
@renatoh

renatoh commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Also the change (that I introduced RE executor initialization) results in no enforced cap/limit on threads. I didn't check if there's one at the JDK HttpClient level. If there's no limit, then it's worth a major-changes-since adoc file note. We should probably have a bit of javadoc somewhere to communicate whatever limit may or may not exist so at least users know. If there's no limit, IMO it's fine. It's straight-forward for a user to enforce via a semaphore if they wish.

@dsmiley
I could not find anything regarding a limit, and I was able to get the thread pool up to 8k threads in some local testing.
I have added some documentation. I've noticed for the HttpJdkSolrClient.executor, we have an attribute on the builder, the user can pass in his own executor if he needs different settings. But we do not have that for httpClientExecutor. I think it would make sense to add it to the builder, what do you think?

@dsmiley

dsmiley commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

But we do not have that for httpClientExecutor.

Maybe I wasn't clear in my last message but I meant to communicate that IMO the executor on the builder should be for HttpClient. It is before this PR; you changed it in this PR. I think you should please change it back. I don't think a user should need to customize the executor used for POST'ing.

…tpClient and not for writing the request bodies
@renatoh

renatoh commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

@dsmiley OK, now I got it. Next try;)

@dsmiley dsmiley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing a changelog

queue,
new SolrNamedThreadFactory(this.getClass().getSimpleName()));
ExecutorUtil.newMDCAwareCachedThreadPool(
new SolrNamedThreadFactory(this.getClass().getSimpleName() + "-http"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to restore the name; no "-http" suffix. The class is for HTTP! (i.e. it doesn't disambiguate). As this is the natural/default executor, I don't think it needs disambiguation.


/**
* Executor used to stream (produce) request bodies into the pipe consumed by the JDK HttpClient.
* This is the "producer" side and may be supplied by the caller.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh? Where? FWIW I don't think we should add to the builder over this minor matter.

Comment thread solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc Outdated
…in-solr-10.adoc

Co-authored-by: David Smiley <dsmiley@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client:solrj documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants