Fronting RabbitMQ Services with REST

  • speed
  • to support multiple programming languages
  • a platform for legacy services
  • to support a large number of services
  • to support mixed payload formats
  • to support mixed protocols
  • to provide fault isolation
  • to support logging and usage reports

ETrade Needed

ETrade Solution

  • ​realized REST can be applied to non-HTTP protocols
  • most services are AMQP-based for performance and fault tolerance reasons
  • legacy services still used request-response
  • bridge the two worlds

Their "aha" Moment

  • ​introduced an API gateway
  • implemented in node.js and Express
  • wanted non-blocking I/O
  • easily could have been Ratpack or vert.x
  • provides protocol conversion
  • provides payload conversion
  • provides service routing
  • aggregates parallel service calls
  • avoids boilerplate code
  • good at REST, leaves business logic to the services

API Gateway

  • ​REST uses URIs to route to services
  • AMQP uses exchanges and routing keys to route to services
  • gateway maps URIs to routing keys
  • GET /account/1234 becomes the key GET/account/{id}
  • the mapping is simple and easily understood
  • all messages get sent to the same exchange and RabbitMQ handles the routing via the key
  • RFC 6570 URI templates easily supported

Routing Technique

  • ​HTTP headers have to be transformed into AMQP headers
  • some headers are common but most are protocol specific
  • AMQP has a "bucket" in its message structure for custom key-value pairs so HTTP headers can be preserved there
  • gateway sets up a one-time listener for the response from the service
  • response from the service is returned back to the caller
  • newer streaming HTTP preferred but not always possible in older clients

Protocol Translation

  • dead letter exchanges used to deal with messages that get rejected, exceed their TTL or when queue lengths are exceeded
  • alternate exchanges used to deal with messages that cannot be routed
  • not mentioned directly but the gateway must have timeouts  in place to avoid waiting for a reply forever 
  • unclear how partial failures are dealt with -- only 4 of 5 aggregated services responded

Handling Failures

  • REST clients preferred JSON
  • AMQP services preferred XML
  • Gateway handles the transformations between the two
  • URI variables get transformed into tags in the XML
  • caching possible if etag and if-matches constructs are used in the HTTP requests
  • should be possible to use content-type meta-data to transform between different versions of payloads

Payload Transformation

  • a service implementation and its exposed API is cleanly separated
  • REST endpoints are easier for QA to test against
  • gateway can emit reportable events to track API usage and failures
  • using Level 2 of the Richardson model (no hyper-media)
  • can virtualize services for different types of testing (replace a real service with a fake one, for example)
  • can use Ratpack or Vert.x for a JVM solution

Observations

  • Ratpack supports the Reactive APIs to simplify serializing the callbacks
  • Java 8 Streams might be another option
  • LMAX Distruptor might be another alternative
  • If possible, use web client APIs that don't block waiting for an answer, such as web sockets
  • having all services publish to a single exchange simplifies event producer code
  • having exchange keys mimic REST URI is a "bleed through" of a protocol

Observations

  • gateway needs to return HTTP status code in addition to failures
  • does this imply that service payloads also provide HTTP status codes?
  • again, might be more "bleed through"
  • gateway provides a nice delineation between public APIs and "behind the firewall" private service APIs.  
  • to work with the gateway, services will have to conform on a set of exchange patterns -- which is probably a good thing
  • allows for efficient binary payloads behind the firewall

Observations

  • unclear if a single gateway or multiple gateways exist
  • a single gateway might become unweildy

Observations

Fronting RabbitMQ Services with REST

By Ronald Kurr

Fronting RabbitMQ Services with REST

How ETrade uses REST to access RabbitMQ -based services

  • 1,362