Kirk Haines

It's Rubies All The Way Down

Ruby is a language with expansive capabilities. One of it's main niches is with web application work. Typically, Ruby is used exclusively in the application container/application layer, with other technologies providing the rest of the stack. Ruby can fill other roles in the application stack, though, so for fun, let's explore a stack that is composed of Ruby software from top to bottom. What would that look like? How would it perform? Why would you do this?

RubyKaigi 2018 https://rubykaigi.org/2018/presentations/wyhaines

RubyKaigi 2018

00:00:00 Hello everyone, I'm Kirk Haines, and today we're going to talk about a unique approach to using Ruby in web applications.
00:00:05 This presentation is kind of a historical survey and a look at pushing the boundaries of what people typically do with Ruby. We will explore if Ruby can be used in areas that are generally not considered for Ruby applications.
00:00:18 A little bit about me: I've been doing Ruby since 2001, and my first professional gig involved developing a web application using Ruby in 2002. That project was a job search application for the Milwaukee Area Chamber of Commerce, designed to match companies looking for college interns with the interns.
00:00:37 Since then, I've worked on numerous sites and apps, multiple web servers, and other related projects. Currently, I work for Cookpad, and you can find me online as 'Kirk Haines' pretty much everywhere.
00:00:54 Now, I've got a lot of slides to cover, and I know I don't have much time, so let's dive right in. When discussing web applications, we often talk about a 'stack.' A stack simply refers to all the software that enables our application to function and interact with end users in the world.
00:01:19 I've identified these key components that make up a modern web application stack. While we may not always use every component, they represent the key elements of a typical stack. Generally, Ruby is primarily found in the application container layer, which I believe is the only layer you consistently find Ruby being utilized.
00:01:51 However, there are other Ruby tools used in the stack, although we typically do not see Ruby in those other layers. For instance, many of you may be familiar with Capistrano, a deployment tool written in Ruby. Or Fluentd, which is a Ruby-based system designed for log aggregation, helping you manage logs efficiently.
00:02:14 Additionally, configuration management tools like Chef or Ansible rely on Ruby for their functionality. Despite Ruby’s utility in the application layer, its role across the entire stack is not commonly acknowledged.
00:02:38 In my personal experience, however, I've developed several production applications over a decade ago that are still running on stacks composed solely of Ruby software from top to bottom. I plan to show you how I achieved this and explored its practical application.
00:03:10 I started working with Ruby before version 1.6.7; my journey began with version 1.6.6. Back then, web development was fundamentally different. There weren't many frameworks or tools available, which made things quite challenging.
00:03:31 Having previously worked in Perl, I found the lack of tools in Ruby limiting. The only libraries I encountered were Emerita for templating and the CGI library inherent to Ruby. There was mod_ruby, which allowed embedding Ruby in Apache, but it came with significant drawbacks.
00:03:54 Around that time, I found a proof-of-concept web framework called Iowa, created by a developer named Abbey Bryant in 2001. This tool was far more effective than anything I had previously seen while using Perl or even the existing Ruby frameworks.
00:04:09 Iowa excelled in its architecture because the web applications ran in separate processes communicating with the web server via sockets.
00:04:25 Eventually, I took over the Iowa project from Abbey Bryant and transformed it into something usable for development. This served as the foundation for my first application in 2002.
00:04:47 Fast forward to today, the stack I developed resembles what we see in modern web applications. Of course, things have evolved; when Ruby on Rails launched, it revolutionized the Ruby ecosystem by introducing a preferred deployment mechanism, predominantly Apache-centric.
00:05:05 Rails used FastCGI for communication between the web server and back-end processes, but this came with challenges. The FastCGI setup was often difficult to manage, impacting server performance.
00:05:28 In 2006, a developer named Zed Shaw introduced a new web server written in Ruby called Mongrel, which quickly gained popularity. Its speed and standards compliance made it the preferred choice for deploying Rails applications, alleviating many of the pain points associated with FastCGI deployments.
00:05:54 At the time, Nginx also started gaining traction, especially since it didn't support FastCGI well. With Mongrel, users could easily utilize Nginx for routing without any major issues.
00:06:20 Interestingly, I avoided Rails in my projects because it was too heavy and resource-intensive for the applications I was working on, which prompted me to continue developing with Iowa.
00:06:41 As I worked on Iowa applications, I faced different deployment scenarios, each requiring unique request representations due to different interfaces—be it through CGI, Mongrel, or FastCGI.
00:07:03 This variety necessitated an abstraction layer that could harmonize these disparate representations, which led me to create something that resembled Rack while working on Iowa.
00:07:37 As Rack gained traction, my own code increasingly integrated into it, transforming the interaction model between Ruby web applications and the web.
00:07:51 The aforementioned Iowa offers fantastic features, including server-side state management, which simplifies handling forms and code interaction, eliminating the need to worry about manual state management.
00:08:16 However, as applications scaled and required more users, managing states across many processes and machines became problematic due to the absence of robust load balancers.
00:08:41 This led me to conceptualize a basic web server that included caching, reverse proxy capabilities, and Iowa session support. Many industry experts advised against doing this in Ruby, asserting the language's limitations in speed.
00:09:06 Contrary to their expectations, it turned out that the performance was quite satisfactory. In fact, initial benchmarks captured about 15,000 requests per second on modest hardware.
00:09:25 This realization sparked the idea that I could expand Ruby’s role throughout the stack, particularly where it’s traditionally not applied.
00:09:46 As of 2009, my production stack was entirely Ruby. I used a reverse proxy I created called Swift Apply, which handled all requests before they reached the application instances.
00:10:08 I also developed a log aggregator named Analoger to collate logging information from across the various systems I managed, addressing a significant gap in the ecosystem.
00:10:30 Handling logs spread across numerous locations was complicated, so I built Analoger as an asynchronous logger to ensure it wouldn’t adversely affect application performance.
00:10:54 When the logging server failed, clients would spool logs locally until the server was restored, at which point it would drain the messages back from storage.
00:11:18 Throughout these developments, I’ve proven it’s possible to leverage Ruby effectively in production environments across several components of the application stack.
00:11:42 I began exploring Ruby on the assumption that while it has historically been seen as slow, there are ways to ensure performance remains at satisfactory levels.
00:12:03 Expanding Ruby’s application into key-value stores and lightweight logging solutions shows that there’s still much potential for Ruby’s versatility.
00:12:26 I also want to highlight technologies like Capistrano, which is widely used as a deployment tool. Drawing from my experience at Engine Yard, I've employed Capistrano for many deployments.
00:12:56 A project to automatically deploy code to the appropriate server following a git push has been particularly intriguing for me.
00:13:14 Tools and scripts like Surf allow for distributed commands across various instances and simplify command execution on servers. This allows you to keep your deployment process smooth.
00:13:35 By combining various tools and approaches to Ruby, I've shown that it is possible to maintain a coherent and efficient stack, integrating Ruby across various layers.
00:14:00 In summation, there are numerous reasons to leverage Ruby in the stack, namely simplicity for specific functions that may not be easily achieved otherwise.
00:14:27 However, it's essential to consider the performance expectations with Ruby, as it is not as fast as C or C++. Generally, the advantages of using Ruby tend to outweigh performance limitations.
00:14:52 While security can be an issue, as fewer individuals scrutinize your Ruby code compared to a battle-tested web server solution, Ruby has proven its resilience.
00:15:12 As we wrap up this presentation, I invite anyone here to inquire more about my experiences or the specifics of employing Ruby in the web stack.
00:15:40 Thank you for your attention, and if you're attending the Cookpad party, feel free to drop by!