Performance Tuning Apache CXF: Caching, Threading, and Serialization Tips
1. Measure before changing
- Profile: Use JFR, YourKit, VisualVM, or similar to identify CPU, memory, GC, and thread bottlenecks.
- Load-test: Reproduce realistic traffic (JMeter, Gatling) so changes are measurable.
2. Caching strategies
- WSDL/Schema caching: Enable WSDL and XSD caching to avoid repeated parsing. Use CXF’s WSDLManager and ResourceManager defaults or set a custom CacheControl for WSDL retrieval.
- Client and endpoint metadata: Cache Service and Endpoint objects rather than recreating them per-request.
- HTTP caching: Configure HTTP cache headers (ETag, Cache-Control) for idempotent GETs. If using a reverse proxy (NGINX, Cloudflare), offload caching there.
- Result caching: Cache expensive computed results using an in-memory cache (Caffeine, Guava, EHCache) with appropriate TTL and eviction policies.
- Marshalling/unmarshalling cache: Reuse JAXBContexts (they are thread-safe and expensive to create) — create once and cache per JAXB context class.
3. Threading and concurrency
- Connector thread pools: Tune servlet container or HTTP transport thread pools (Jetty, Tomcat, Undertow). Increase max threads for higher concurrency; match thread pool size to CPU and blocking behavior.
- Non-blocking IO: Use non-blocking transports (CXF with Jetty NIO or async HTTP conduit) for high concurrency with I/O-bound workloads to reduce thread count.
- Executor services: Configure CXF’s asynchronous features with properly sized ExecutorService instances to avoid unbounded queueing.
- Avoid synchronized hotspots: Eliminate global locks in service implementations and interceptors. Use concurrent collections and lock-free patterns.
- Request-scoped state: Keep handlers/stateless services to allow safe concurrent processing; avoid mutable static fields.
4. Serialization and message processing
- JAXB optimization: Reuse JAXBContext and marshallers/unmarshallers where possible; configure Marshaller.JAXB_FORMATTEDOUTPUT = false in production.
- Alternative serializers: For JSON APIs, prefer Jackson (faster and more configurable) via cxf-rt-rs-json or jaxrs providers; for binary payloads consider ProtoBuf if compatible.
- Streaming: Use streaming APIs (StAX for XML, Jackson streaming for JSON) to avoid building full in-memory DOM for large payloads.
- Compress responses: Enable gzip compression for large responses at CXF or reverse proxy level; balanced with CPU cost.
- Minimize headers and attachments: Avoid large SOAP headers or MTOM attachments unless necessary; use optimized attachment handling when needed.
5. CXF-specific tuning knobs
- Conduits and Transports: Tune HTTP conduit settings (connectionTimeout, receiveTimeout, maxConnections) for clients. Use connection pooling for outbound calls.
- Interceptors: Keep interceptor chains minimal; expensive interceptors (logging, security) should be conditional or applied only where needed.
- Logging: Use sampling or async logging (Logback AsyncAppender) to reduce overhead. Avoid full payload logging in production.
- Cache control for schema/WSDL: Configure Spring beans or CXF properties like org.apache.cxf.wsdl.service.factory to improve reuse.
6. Memory and GC
- Object creation: Reduce per-request object churn (reuse buffers, StringBuilder, byte[] via pooling).
- Byte buffer pools: For high-throughput binary data, use pooled byte buffers (Netty/Jetty pools).
- Tune JVM GC: Choose G1 or ZGC for low-pause requirements and tune heap sizes based on profiling.
7. Network and infrastructure
- Load balancer configuration: Use keep-alive, connection pooling, and health checks to reduce connection churn.
- TLS offload: Terminate TLS at a proxy when possible to reduce CPU on service nodes.
- CDN and edge caching: Offload static or cachable responses to CDN.
8. Practical checklist to apply
- Baseline with profiling and load tests.
- Cache JAXBContext, WSDL/schema, and Service objects.
- Tune servlet/container thread pools and consider non-blocking IO.
- Switch to Jackson streaming for JSON and reuse marshallers.
- Reduce interceptor usage and enable async logging.
- Enable compression and tune HTTP conduit pooling.
- Re-run load tests and iterate.
9. Quick config snippets
- Reuse JAXBContext (Java):
java
private static final JAXBContext CTX = JAXBContext.newInstance(MyClass.class);
- Disable formatted output:
java
marshaller.setProperty(Marshaller.JAXB_FORMATTEDOUTPUT, Boolean.FALSE);
- HTTP conduit example (cxf-client.xml):
xml
<http:conduit name=“{http://…}MyServicePort.http-conduit”> <http:client ConnectionTimeout=“60000” ReceiveTimeout=“60000” MaxRetransmits=“1”/> <tls:client DisableCNCheck=“true”/> </http:conduit>
Apply changes incrementally and measure impact after each.
Leave a Reply