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
Made with Slides.com