00:00:16.560
All right. You guys ready to talk about SOA (Service-Oriented Architecture)?
00:00:26.240
I'm Josh. Hi, how are you doing? I'm the CTO at Optoro, where we make software for retailers to help them deal with their inventory at scale. I'm working on a project called Rack-AMQP.
00:00:38.879
Rack-AMQP is a collection of various projects, including an RFC and some client libraries. Most notably, it includes Jackalope, which is a new Ruby web application server similar to Unicorn, Passenger, or Thin, but it's special purpose: it’s designed for service-oriented architectures and does not actually speak HTTP at all.
00:01:00.079
So why am I doing this crazy thing? Well, my app drove me to it. My app is huge and really complicated. This is kind of a services diagram of my app or where we'd like to go with it.
00:01:10.479
There are over 350 models in one Rails application. The test suite takes over eight hours, which is quite a headache. So we decided to move forward by breaking it up into smaller applications that can work together, and of course, that means SOA.
00:01:25.119
Now, SOA often comes with a lot of baggage. When you think about SOA, you often think about enterprise service buses, strict interface definitions, and versioning. It's a lot of complexity, which creates extra load balancers, increased configuration, and more distributed tracing and monitoring. Honestly, it's a real pain, so I have my reservations about SOA.
00:01:55.439
However, when you get down to it, SOA is not all that bad. SOA is really just about independent actors communicating and working together to accomplish something useful. It can actually help mitigate complexity by enforcing simplification since each service only has to focus on its own 'bubble.' It doesn't have to think about everything else going on in the entire system; your system architect can manage the big picture.
00:02:49.440
When we talk about how these independent actors interact, we have to consider that communication is key because how they communicate determines how your application behaves. The types of communication you use impact the kind of application you can write. The common pattern we are most familiar with is direct messaging.
00:03:06.080
As programmers, we are used to objects sending messages to one another, just like with HTTP where I can send a message to my friend and expect a response. But what's more than that is the need for different kinds of messaging structures. We want to publish that something happened in our system and have people subscribe to that event to take some action, thereby decoupling our services.
00:03:32.949
Yet, as Rails developers, we continuously lean towards HTTP for our web applications. It's what we know, allowing for direct messaging. This becomes a sticking point when most SOAs start by building web applications that communicate via HTTP. But what we really want is a transport mechanism that is data structure independent.
00:04:00.239
HTTP specifies that there needs to be a body in the request but doesn't dictate the format of that body. We desire our transport to be fast, open, transparent, understandable, debuggable, observable, and flexible. But is HTTP all of those things?
00:04:21.919
We need not only direct request-response messaging, like RPC, but also publish-subscribe and broadcasting capabilities. We also want to avoid the additional overhead of more load balancers, more SSL certificates, and the complexity involved in distributed logging to get insights into what’s happening across our services.
00:05:02.720
HTTP is great for RPC, but there’s a better alternative, and that is AMQP (Advanced Message Queuing Protocol). AMQP is agnostic to the data being transmitted, extremely fast, open, and it supports various messaging patterns beyond direct messaging.
00:05:05.039
CRABAMQP is centralized, which is beneficial for a service-oriented architecture, as it allows you to manage and pay attention to a single point for all message routing. The challenge, however, lies in that it is not what we are traditionally familiar with as web developers, which can make the transition daunting.
00:05:25.919
The Rack AMQP project I’m working on is designed to make AMQP simple. We aim to introduce as few opinions as possible, giving you a stepping stone into the world of AMQP. This project allows you to start with familiar concepts while integrating more advanced AMQP features without requiring a complete overhaul of your knowledge or practices.
00:06:00.319
Moreover, because Rack AMQP is built on Rack, which we already use daily in our Ruby web applications, we can continue to leverage our existing knowledge and develop locally on our machines using the systems we are comfortable with. When deploying, you just deploy to Jackalope instead of Unicorn or Passenger, and suddenly you’re part of the AMQP world.
00:06:22.160
So how does this work? First, let’s take a closer look at AMQP itself. AMQP is an open standard developed by OASIS, and it employs a centralized distribution pattern that allows for various types of messaging, including the publish-subscribe model.
00:06:52.400
AMQP messages have headers and bodies similar to HTTP, containing well-known fields such as content type and priority. We can even leverage conventions from HTTP to adapt AMQP, mapping its structures to fit familiar patterns. For instance, we can create similar headers and body formats to HTTP to ease the transition for developers.
00:07:05.440
The AMQP-over-HTTP RFC simply defines the necessary structure to enable interoperability between these paradigms. Another goal is to facilitate the seamless integration of different programming languages and platforms with AMQP, ensuring that developers have consistent documentation to refer to for constructing AMQP compatible servers.
00:07:42.960
To illustrate how HTTP works, consider that when we send a request, we target a specific server at a specified IP address and port. We issue the request with HTTP verbs, paths, headers, and bodies, receiving a response complete with a response code. Mapping this HTTP structure into AMQP terms is all about taking the concepts we are familiar with and adapting them to AMQP.
00:08:01.360
For context, AMQP supports the RPC messaging pattern, which is inherently what HTTP does. The AMQP HTTP RFC outlines these mappings clearly to provide consistency and clarity.
00:08:06.560
One of the features of AMQP is its asynchronous model. When using AMQP, you create a response queue that you will listen to on the broker. By sending a message along with the designation of the response queue, you can mimic HTTP's synchronous behavior where you wait for an immediate response.
00:08:49.200
This way, we can maintain the synchronous requests we are accustomed to but still utilize the asynchronous capabilities of AMQP for efficiency. Given that we leverage Rack in our applications, it allows us to subscribe to a queue on the server and unpack the incoming messages, creating an environment similar to an HTTP ecosystem.
00:09:12.960
So, this is how Jackalope functions: it emulates HTTP for our Rack applications. The beauty of this system is that you do not have to modify your existing code; you can deploy your apps directly to Jackalope, and it will be operating over AMQP instead of HTTP.
00:09:31.200
Now, let’s discuss production. You'll need to choose a broker when using AMQP, and RabbitMQ is a popular option. It is a well-known AMQP broker used by major companies like Google, VMware, and NASA due to its scalability and robust features.
00:09:52.280
In terms of managing the RabbitMQ server, it provides a user-friendly management console that gives insights into the system, tracking queues, their depths, and offering a general overview without overwhelming details, which is crucial for understanding what is happening in your distributed system.
00:10:13.040
Additionally, you must consider how to interface with the real world. While AMQP excels behind the scenes, it’s vital to maintain communication with clients, which is where we see a mixed architecture at Optoro. We have RabbitMQ at the center, with services on Jackalope communicating with it and API services still running on Unicorn for external interactions.
00:10:59.280
The API will then translate and relay requests through AMQP to the inner services. Each internal service comes with a client gem to help abstract the transport complexities, making it seamless for consumers to interface with the correct underlying technology.
00:11:19.760
Part of our effort includes AMQ Party, which provides an API-compliant version of HTTP Party. This lets you swap HTTP Party for AMQ Party in your application without changing much in your codebase, ensuring that everything continues to work.
00:11:49.840
We also have a Rack AMQP client built on Bunny, making it easy to get started with AMQP. The goal is to streamline communication within applications, ensuring users can easily send requests to their target queues and receive responses effectively.
00:12:27.280
As for performance, we conducted benchmarks comparing the same requests using AMQP and HTTP. During testing, AMQP requests took significantly less time than those made over HTTP, which was somewhat surprising given the nascent state of Jackalope.
00:13:09.920
The reason for AMQP's speed advantage lies in how TCP connections are established. Each HTTP request tends to open and close a new connection, which includes a lengthy TCP handshake process. In contrast, AMQP maintains a persistent connection, reducing overhead and speeding up communications.
00:13:49.600
This persistent connection allows for multiplexing information, leading to efficient internal communications. While it’s possible to implement keep-alive connections in HTTP, most developers do not typically do so, emphasizing the inherent efficiency of using AMQP.
00:14:17.600
To wrap up, I want to mention a few influential resources that inspired our direction. This is a deviation from the traditional Rails architecture, and features discussed in talks around hexagonal Rails certainly motivated us to explore this model more deeply.
00:14:54.400
Martin Fowler's recent writing on microservices also resonates strongly with our goals, showcasing how independent services collaborate without the bloat often associated with SOA. The Ruby AMQP gem documentation further clarifies how AMQP operates within the context of Ruby applications, complementing RabbitMQ’s own extensive guidance.
00:15:30.680
And lastly, there is a fascinating educational piece from a university in Singapore about how HTTP works, which includes insightful diagrams making it easier to understand its mechanics. If you haven't already, I highly recommend checking it out.
00:16:08.960
Thank you again for joining me today. I’m Josh, and you can find me on Twitter at @jszmajda. I’m the CTO at Optoro, where we help retailers manage returns and excess inventory so they can maximize their value and speedily handle logistics. I'm also the host of the Ruby Hangout, a virtual meetup allowing developers to connect and discuss Ruby-related topics regardless of local availability. Finally, I want to give a special thanks to Jonathan from my team for supporting the development of Jackalope. The source code is available on GitHub at github.com/rack-amqp/rack-amqp, and I welcome any questions you might have about the project or the talk today.