Repository navigation
Conversation
Port the outbound write protection from java-tron PR #7071 (commit 52bb599e378a18719c22a81ae0ee836d186f38dd). Reserve framed payload bytes before event-loop submission and release reservations when writes complete or fail. Close a peer above 200 MiB; at 500 MiB shared pending data, evict the largest writer and wait for its writes to be released before selecting another global victim. The shared threshold triggers eviction, not a hard admission cap. Close connections with writes pending for ten seconds. Preserve libp2p's existing connection lifecycle and disconnect cooldown behavior. Port budget regression tests and isolate the Channel write-timeout test from java-tron's ChannelCoreTest.
|
Since this change moved here from tronprotocol/java-tron#7071 with the same code (only the logger name differs), here is a consolidated version of the points raised there:
|
|
The current policy prioritizes the connection with the most pending data so that, under global resource pressure, we can release more of the budget with fewer disconnections. It does not classify that peer as malicious. An honest syncing peer can indeed become the victim; this is a trade-off in overload protection. Selecting solely by the time of the last completed write could instead choose a connection with little pending data that has not completed a write for a long time, releasing too little of the budget. Conversely, a connection that keeps completing small writes can still accumulate an increasing backlog. Write progress can therefore be considered in a future evaluation, but I would retain the current backlog-based selection policy for now. Being trusted or configured as an active peer does not, by itself, prevent a connection from creating resource pressure. Cooldown and reconnection behavior currently follow the existing connection-management logic. Outbound and trusted connections already receive different admission handling, so the 60-second reconnection restriction does not apply uniformly to every connection. Distinguishing the trigger and logging the pending data at eviction would help diagnosis and can be considered as a follow-up observability improvement. Regarding the thresholds, 100 maximum-size blocks is an extreme batch estimate; it does not mean normal syncing will have that much data pending simultaneously. Based on our production observations, blocks are typically around 100 KB, or roughly 10 MB per batch, and completed writes continuously release the budget. This does not guarantee that every large-block or congested-network scenario will avoid triggering the protection. The current budget accounts for pending write bytes including the frame prefix. The 500 MiB threshold triggers soft eviction; it is neither an exact measure of direct-memory usage nor a hard cap on it. Allocator capacity rounding and other memory overhead must be considered separately. Making the parameters configurable has value, but the defaults still require workload measurements and cannot be derived directly from only the sync batch size or the JVM direct-memory limit. I agree that writability and application-level backpressure are suitable for a separate follow-up. They require java-tron to implement pause/resume behavior and bounded pending-request management. Merely exposing |
What does this PR do?
Add pending-write accounting and timeout handling to improve TCP connection resource management.
The shared threshold triggers asynchronous eviction rather than enforcing a hard global admission limit.
Why are these changes required?
This PR has been tested by:
Follow up
Extra details