Click here to load reader

Scaling RESTFul Services With JAX-RS - · PDF file Speaker’s Qualifications RESTEasy project lead • Fully certified JAX-RS implementation JAX-RS JSR member • Also served on EE

  • View
    0

  • Download
    0

Embed Size (px)

Text of Scaling RESTFul Services With JAX-RS - · PDF file Speaker’s Qualifications RESTEasy...

  • Scaling RESTFul Services With JAX-RS

    Bill Burke

    Fellow

    JBoss, a division of Red Hat

    [email protected]

  • Agenda

    � Caching

    � Encoding

    � Concurrency

    � Asynchronous HTTP

    � Asynchronous Jobs

  • Speaker’s Qualifications

    � RESTEasy project lead

    • Fully certified JAX-RS implementation

    � JAX-RS JSR member

    • Also served on EE 5 and EJB 3.0 committees

    � JBoss contributor since 2001

    • Clustering, EJB, AOP

    � Published author

    • Books, articles

  • Caching

    Cache is King

  • Web Caching

    � Why?

    • To reduce latency

    • To reduce network traffic

    � Who?

    • Browsers

    • Content Delivery Networks (CDNs)

    � Akamai, Limelight

  • HTTP Caching Features

    � Caching: allowed or not allowed

    � Expiration

    � Intermediary caches allowed or not (CDNs)

    � Validation

    • Conditional GETs

    � Storable or not Storable

    � Extendible caching semantics

  • Knowing When to Cache?

    � How does a browser/CDN know when to cache?

    • Expires header

    • Cache-Control header

    • Validation Headers

    � Last-Modified

    � Etag

    • If none of these set, don’t cache

  • Expires Header

    � Set by the server

    � Simple date into the future that cache expires

    � Deprecated way of controlling cache semantics

    Expires: Tue, 17 Mar 2009 16:00 GMT

  • Cache-Control Header

    � Preferred way of setting cache parameters

    � Rich set of functionality

    � Used by both server and client (request/response) to

    set caching semantics

    � Always takes precedence over Expires

  • Cache-Control Response Directives

    � public - cacheable by anybody

    � private - no CDNs allowed, only client should cache

    � no-cache - don’t cache ever

    � max-age - time in seconds the cache is valid

    � s-maxage - time in seconds a shared cache valid (CDN)

    � no-store - don’t persist cache entries

    � no-transform - don’t transform into a different type

  • Cache-Control Response Directives

    � must-revalidate - client should not hold/use stale

    entries

    � proxy-revalidate - CDN should not hold/use stale

    entries

    Cache-Control: no-cache Cache-Control: private, max-age=3000

  • JAX-RS and Cache-Control

    @Path(“/orders”) public class OrderService {

    @Path(“/{id}”) @GET @Produces(“application/xml”) public Response getOrder(@PathParam(“id”) int id) { … CacheControl cc = new CacheControl(); cc.setMaxAge(3000); return Response.ok(order)

    .cacheControl(cc).build(); }

    }

  • RESTEasy and Cache-Control

    @Path(“/orders”) public class OrderService {

    @Path(“/{id}”) @GET @Produces(“application/xml”) @Cache(maxAge=3000) public Order getOrder(@PathParam(“id”) int id) {

    … }

    @Path(“/{id}”) @GET @Produces(“application/xml”) @NoCache public Order getOrder(@PathParam(“id”) int id) {

    … }

    }

    Only on 200, OK response

  • Validation Headers

    � When cache is stale, client can ask server if cache still

    valid

    � To be able to revalidate client needs additional headers

    beyond Cache-Control from a server response

    • Last-Modified - a date when the resource was last modified

    • ETag - a unique hash-like key that identifies a version of the resource

    � Client should cache these headers along with response

    body

  • Validation Headers and

    Conditional GETs

    � When client determines cache is stale it does a GET

    with one or both of these headers set

    � If-Modified-Since

    • With value of server’s Last-Modified header

    � If-None-Match

    • With value of server’s Etag header

  • Validation Headers and Conditional

    GETs

    � Server examines If-Modified-Since and/or If-None-

    Match headers

    � Is the client cache still valid?

    • Send a 304, “Not Modified” response code with no body

    • Optionally send updated Last-Modified and Cache-Control response

    headers

    � Is the client cache not valid anymore?

    • Send 200, “OK” with new resource body

    • Optionally send new Last-Modified, Etag, and/or Cache-Control

    response headers

  • JAX-RS and Validation

    public interface Request {

    ResponseBuilder evaluatePreconditions(EntityTag eTag);

    ResponseBuilder evaluatePreconditions(

    Date lastModified);

    ResponseBuilder evaluatePreconditions(

    Date lastModified, EntityTag eTag);

    }

    Return null if conditions not met

    Return a builder with response

    code set to 304

  • JAX-RS and Validation @Path(“/orders”) public class OrderService {

    @Path(“/{id}”) @GET @Produces(“application/xml”) public Response getOrder(@PathParam(“id”) int id,

    @Context Request request) { EntityTag tag = … get new app-specific tag; ResponseBuilder builder = null; builder = request.evaluatePreconditions(tag); CacheControl cc = new CacheControl(); cc.setMaxAge(3000); if (builder != null)

    return builder.cacheControl(cc).build();

    … get order … return Response.ok(order)

    .cacheControl(cc).build(); }

    }

  • Caching Facilities

  • RESTEasy Client Cache

    � Acts like a browser minus persistence

    • In memory only

    � Does validation and conditional gets

    � Sharable “Browser” cache instances

    � Works with raw request or proxy framework

  • RESTEasy Client Cache @Path(“/orders”) public interface OrderServiceProxy {

    @GET @Produces(“application/xml”) @Path(“{id”} Order getOrder(@PathParam(“id”) int id);

    }

    OrderServiceProxy proxy = ProxyFactory.create( “http://example.com”);

    BrowserCache cache = CacheFactory.makeCacheable(proxy);

    // proxy instance now will cache responses and do // conditional GETs

  • Squid

    � Caching proxy server (not JBoss)

    • www.squid-cache.org

    � Supports caching HTTP, HTTPs, FTP and more

    � Advanced Content Routing and Load Balancing

    � Very popular

  • RESTEasy Server Cache � Local in-memory cache

    • Sits in front of JAX-RS service

    • Caches marshalled data

    • If service sets Cache-Control header with a max age

    � Response will be cached

    � Update Cache-Control header on cache hit

    � Automatically generates Etag headers

    • Md5 hash of content

    � Handles Cache Validation automatically

    � If client sends Etag and server cache is stale

    • Invoke service

    • Md5 hash the data

    • If same as If-None-Match, return NOT MODIFIED

    • Recache the response

  • Caching Conclusion

    � HTTP has rich caching semantics

    • Cache expiration

    • Browser and CDN controls

    • Persistence controls

    • Revalidation

    � JAX-RS provides some help

    • CacheControl object

    • Revalidation methods

    � Caching Infrastructure and Tools available

    • Browser

    • Squid

    • RESTEasy Client and Server Cache

  • Concurrent Updates

  • Conditional PUTs and POSTs

    � HTTP has protocols for managing concurrent or stale

    writes

    � Can prevent client from modifying and updating a stale

    copy of a resource

    � Like cache validation relies on:

    • Last-Modified

    • ETag

  • Conditional PUTs and POSTs

    � When doing a PUT or POST client sends these request

    headers

    • If-Unmodified-Since - value of Last-Modifed

    • If-Match - value of Etag

    � If the resource hadn’t been modified since or matches

    ETag value

    • Perform the update

    � If the resource has been modified or doesn’t match

    ETag

    • Send a 412, “Precondition Failed” response code

  • JAX-RS and Condition PUTs

    public interface Request {

    ResponseBuilder evaluatePreconditions(EntityTag eTag);

    ResponseBuilder evaluatePreconditions(

    Date lastModified);

    ResponseBuilder evaluatePreconditions(

    Date lastModified, EntityTag eTag);

    }

    Return null if conditions met

    Return a builder with response

    code set to 412

  • JAX-RS and Conditional PUT @Path(“/orders”) public class OrderService {

    @Path(“/{id}”) @PUT @Produces(“application/xml”) public Response updateOrder(@PathParam(“id”) int id,

    Order order, @Context Request request) {

    EntityTag tag = … get current app-specific tag; ResponseBuilder builder = null; builder = request.evaluatePreconditions(tag);

    if (builder != null) return builder.build();

    … update order … return Response.noContent().build();

Search related