Apache CXF vs. Spring Web Services: Choosing the Right Java SOAP/REST Framework

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

  1. Baseline with profiling and load tests.
  2. Cache JAXBContext, WSDL/schema, and Service objects.
  3. Tune servlet/container thread pools and consider non-blocking IO.
  4. Switch to Jackson streaming for JSON and reuse marshallers.
  5. Reduce interceptor usage and enable async logging.
  6. Enable compression and tune HTTP conduit pooling.
  7. 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.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *