Performance Tuning of a Spring Backend Service to Reach 500 Requests per Second
The article details a step‑by‑step performance investigation and optimization of a Spring‑based ToB system, covering slow SQL, thread‑pool tuning, JVM memory adjustments, excessive logging, and bean‑creation overhead, ultimately improving throughput from 50 req/s to nearly the required 500 req/s.
The author describes a ToB system that originally had no load testing and was required by a new client to achieve at least 500 requests per second on a single node.
Initial calculations suggested 200 ms per request would be enough, but a load test with 100 concurrent users only produced 50 req/s and CPU usage near 80%.
Analysis began by looking for blocking points such as locks and slow operations. Latency alerts were added for response time, remote calls, Redis access, and SQL execution.
Log inspection revealed a slow update table set field = field - 1 where type = 1 and filed > 1; statement that caused lock contention; the query was moved to asynchronous execution, reducing the maximum response time from 5 s to 2 s and the 90th percentile from 4 s to 1 s, roughly doubling throughput.
Further investigation showed long gaps in logs caused by thread switches, excessive logging, and possible stop‑the‑world pauses. The log level was raised to DEBUG, thread pools were consolidated to keep total core threads under 50, and JVM heap was increased from 512 MB to 4 GB, which lowered YGC frequency.
CPU usage remained high, prompting a deeper look at bean creation. Frequent calls to BeanUtils.getBean(RedisMaster.class) (prototype‑scoped) triggered many createBean operations, each performing extensive initialization and proxy creation. The code was changed to instantiate Redis objects directly with new RedisMaster() , eliminating the overhead.
The author also noted that frequent time‑measurement code (using System.currentTimeMillis() or Hutool's StopWatch ) adds noticeable cost under high concurrency.
Final results showed significant improvements across MySQL configuration, code refactoring (async execution, thread‑pool tuning, Tomcat and Druid settings), and JVM tuning (memory size and GC). The overall process took four days, involving many trial‑and‑error steps.
In conclusion, the author emphasizes the importance of systematic performance analysis, understanding the impact of locks, bean creation, logging, and thread management, and plans to continue studying performance‑optimization techniques.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.