Tung Nguyen

Summarized using AI

Jets: The Ruby Serverless Framework

Tung Nguyen • May 17, 2019 • Sofia, Bulgaria

Jets: The Ruby Serverless Framework

In his presentation at Balkan Ruby 2019, Tung Nguyen introduces "Jets: The Ruby Serverless Framework," which he developed to enable native use of Ruby in serverless applications. He shares insights on AWS's Lambda and how Jets provides a simplified way to create serverless applications using Ruby.

Key Points Discussed:

  • Introduction to Serverless Frameworks:

    • The concept of serverless computing and the significance of AWS Lambda in the cloud ecosystem.
    • AWS's announcement of Ruby support in Lambda highlighted the need for Ruby developers to have a robust serverless framework.
  • Benefits of AWS Lambda:

    • Avoidance of server management, allowing developers to focus primarily on writing code.
    • Automatic scaling of functions without manual configuration.
    • Economic model of pay-per-request offering significant advantages, especially for startups and personal projects.
  • Serverless Architecture Components:

    • Description of foundational AWS services like Lambda, API Gateway as a routing service, and CloudWatch used for scheduling.
    • Explanation of DynamoDB and RDS Aurora for database management within serverless applications.
  • Common Challenges and Considerations:

    • Addressing limitations such as RAM and code size constraints in AWS Lambda.
    • The cold start problem in Lambda, illustrated with examples of how to mitigate it through optimal RAM allocation and pre-warming functions.
  • The Jets Framework:

    • How Jets simplifies the creation of serverless applications by adopting a Ruby-centric approach rather than a configuration-heavy framework like YAML.
    • Jets efficiently converts Ruby methods into Lambda functions, aiding the development of traditional MVC architectures even in a serverless environment.
  • Development Process and Best Practices:

    • Guidance on how to set up a serverless application using Jets, emphasizing the structure, including app controllers, models, and views.
    • The importance of local testing and continuous integration in the serverless development lifecycle.

Conclusions and Takeaways:

  • Tung emphasizes that Jets enhances Ruby developers' experience in serverless architecture, making it user-friendly and intuitive.
  • The future of serverless development with Ruby looks bright, offering robust solutions that cater to dynamic, scalable application needs.
  • Engaging with the evolving serverless ecosystem is critical for maximizing development efficiency and innovation.

Tung encourages developers to embrace the simplicity and power of Jets for developing Ruby-based serverless applications.

Jets: The Ruby Serverless Framework
Tung Nguyen • May 17, 2019 • Sofia, Bulgaria

Balkan Ruby 2019

00:00:20.300 All right, so the title of my presentation is "Jets: The Ruby Serverless Framework".
00:00:26.519 I wrote it basically just for fun. I wanted to use Ruby in a way that felt like a native serverless framework.
00:00:31.650 So this is the end result of that, and today I'll cover how that works.
00:00:37.649 The emcee did a great job introducing me, so I think it will be a little repetitive now, but here we go.
00:00:43.710 This is the traditional background slide about who I am, my name, what I do, all those fun things.
00:00:51.030 My name is Tung Nguyen, and I run a DevOps consultancy called Blocks, focused mainly on software and media bias in DevOps tooling.
00:00:57.149 I love DevOps tools, and I actually built our written Ruby for my work in the space. I was honored to be recognized as an AWS Container Hero.
00:01:04.320 It was quite a big honor for me last year, as there are only five of us in the world.
00:01:10.049 One of the tools I built is called Roll Call, which helps deploy Docker containers onto ECS.
00:01:15.659 I also have created other tools in this space, such as a CloudFormation template and another one called Jack for Elastic Beanstalk deployments.
00:01:21.330 But today, we'll talk about Jets, this Ruby serverless framework.
00:01:27.180 I think the reason why we're here is that last November, at the re:Invent event, I took this picture: AWS announced official Ruby support for their Lambda runtime.
00:01:33.930 Before that, Ruby was considered a second-class citizen in the serverless world.
00:01:40.439 There were a bunch of other languages supported, like Node.js, Python, Go, and even C#, but no Ruby.
00:01:47.880 I felt that it took them a long time to do this, but finally, when they announced it, I was ecstatic.
00:01:53.490 It felt like an early Christmas present to me, as Ruby has a new release every December.
00:02:00.270 This is a big deal because it puts Ruby in the first-class seat in the serverless world.
00:02:06.869 A good way to explain what a Ruby serverless framework does is to cover some essentials in the serverless world, as this is relatively new to folks not involved here.
00:02:12.900 Let's cover the AWS compute offerings.
00:02:18.450 Currently, in this diagram, on the left side, we have EC2, which stands for Elastic Compute Cloud. Essentially, it's a virtual machine.
00:02:24.870 You can spin those up pretty quickly, in about two or three minutes, giving you full control of the operating system.
00:02:30.150 But with that control, you also have to manage the server yourself.
00:02:36.840 Moving from left to right in the diagram, ECS stands for Elastic Container Service.
00:02:42.209 A very easy way to describe ECS is that it allows you to run Docker containers on EC2 or their Fargate offering.
00:02:48.090 It's essentially a managed service that helps you run Docker containers.
00:02:53.730 To the right, we have Lambda, which is AWS's serverless offering.
00:02:59.400 This is a bit of an oxymoron, as people call it serverless—yet, to be serverless, you need servers.
00:03:05.849 The term is catchy, and many people embrace it, but it doesn't make much sense.
00:03:12.629 Serverless is essentially just a way to run code without managing the server.
00:03:17.760 A better way to describe it is that it is functions as a service.
00:03:23.069 You don't have to worry about the server; AWS manages that for you. You just focus on your code.
00:03:30.750 The benefits of AWS Lambda include no server management, continuous scaling, and a pay-per-request model.
00:03:37.229 The first benefit is that you don’t manage the server. This means you don’t have to worry about security upgrades, OS patching, or instance type upgrades.
00:03:44.639 There are teams of AWS engineers dedicated to these tasks, allowing you to focus on your code.
00:03:50.939 Another benefit is the ability to continuously scale. With EC2, you need to set up auto-scaling rules.
00:03:57.090 Without auto-scaling, even though it's impressive, you still have to configure your rules.
00:04:03.900 With AWS Lambda, it scales for you automatically, which is a significant feat of engineering.
00:04:10.979 Finally, there’s the pay-per-request model, which charges you based on the number of requests and the execution time.
00:04:18.000 This is interesting if you fit within the free tier, where you can get a million requests per month for free.
00:04:23.400 If you want additional staging environments with EC2, you still need to pay a standard fee.
00:04:28.500 However, with AWS Lambda, you can essentially run it for free.
00:04:35.340 I also want to address some of the serverless types; it’s a little hyped.
00:04:42.090 Let's talk about some AWS Lambda considerations. The first is RAM.
00:04:48.420 With AWS Lambda, you can allocate between 128 MB and 3 GB of RAM.
00:04:54.030 In the Ruby world, if you're running a web server, you configure the number of processes and threads.
00:04:59.100 A typical Rails application is about 500 MB of RAM footprint, so for six threads and six processes, you'd use about 3 GB.
00:05:05.310 However, in AWS Lambda, you don’t configure the server; you configure the function.
00:05:11.370 So, if your Ruby process consumes 3 GB of RAM, you might have other issues rather than just RAM.
00:05:17.580 Secondly, let's talk CPU, as people often worry about CPU resources.
00:05:23.850 In my experience, most application limitations tend to be about RAM rather than CPU.
00:05:29.520 In AWS Lambda, CPU is allocated proportionately based on the amount of RAM you allocate to the function.
00:05:36.330 The magic number is around 1.5 GB of RAM, where you get dual CPU cores.
00:05:42.450 Most applications should be fine unless you're doing something intensive like Bitcoin mining.
00:05:48.420 Network speed isn’t a major concern either. If your application is slow, it's often due to the application code.
00:05:54.030 Even with smaller instance types in AWS, the network speed is generally adequate.
00:06:01.020 Lambda functions can execute for a maximum of 15 minutes, which could be a concern for long-running jobs.
00:06:07.890 However, if it's a web request, no user is going to wait for 15 minutes.
00:06:13.680 Another consideration is the code size limit, which is 256 MB for your application code and gem library dependencies.
00:06:18.960 Some Ruby applications can have large gem dependencies, so consider this when designing your application.
00:06:25.290 If your application is more than 256 MB, AWS Lambda might not be a good fit.
00:06:31.770 Now let's discuss cold starts, which is something people often complain about.
00:06:38.640 When the first request comes in, AWS Lambda spins up a container for the service.
00:06:42.309 If you're too conservative with your RAM allocation, this can take about 1 to 1.5 seconds.
00:06:50.000 However, if you allocate at least a gigabyte of RAM, I've seen that cold start times can drop to about 500 milliseconds.
00:06:58.000 Subsequent requests then usually take only a few milliseconds.
00:07:05.000 This reminds me of something in Rails called Russian Doll caching.
00:07:13.000 With dynamic cache keys, if the update time changes, the cache has to be fresh.
00:07:20.000 So if you're generating requests, this takes time and most users do not mind.
00:07:24.000 For a workaround with cold starts, you can pre-warm your functions.
00:07:30.000 One solution in the serverless world is to have a Lambda function that calls your other functions periodically.
00:07:37.000 The Jets framework has pre-warming configured, which I’ll discuss later.
00:07:44.000 Now we need to discuss API Gateway.
00:07:49.000 You can think about API Gateway as a front door to your application.
00:07:55.000 When a user request comes in, API Gateway routes it to a Lambda function and returns the response.
00:08:01.200 API Gateway acts like RESTful API, allowing users to hit the paths using different HTTP verbs.
00:08:07.000 CloudWatch is another essential component.
00:08:13.500 Many of you may know CloudWatch for its centralized logging capabilities.
00:08:18.000 It includes a feature called scheduled event rules, which is basically a way to repeatedly call a function periodically.
00:08:24.600 This acts as a scheduler, managed for you, similar to running a Heroku clock process.
00:08:31.000 To summarize the service components, we have Lambda, which is functions as a service, API Gateway, which is routes as a service, and CloudWatch, which is a scheduling service.
00:08:38.600 When you combine all these components, you can create a traditional Web API architecture using entirely serverless components.
00:08:45.000 User requests come in and hit an API Gateway, triggering multiple Lambda functions.
00:08:52.000 These Lambda functions can interact with two types of backend data storage: DynamoDB and RDS Aurora.
00:08:59.000 DynamoDB is a managed NoSQL database service that scales up and down based on requests.
00:09:06.000 RDS Aurora is a relational database service that also scales according to demand.
00:09:12.000 At the bottom of this architect diagram, CloudWatch handles the scheduled events.
00:09:17.000 Now, let’s go through some quick code examples to explain how Jets works.
00:09:24.000 The console refers to the web browser where you can easily create a function.
00:09:30.000 In the browser, you specify your function name, select Ruby runtime, and click create.
00:09:36.000 Once created, you'll see an IDE in the browser where you can define your Lambda function.
00:09:43.000 The handler has two parts: the name of the file and the Ruby method within it that gets invoked.
00:09:50.000 This Lambda function has a specific signature, accepting two keyword arguments: 'event' and 'context'.
00:09:56.800 The example returns a hash structure with a status code and body.
00:10:03.600 It only takes a few minutes to set this up in the serverless environment.
00:10:09.000 Next, you'll want to set up API Gateway, which can also be done from the browser.
00:10:15.200 You’ll choose the protocol, rest, and create a new API by providing a name.
00:10:22.100 Next, you need to set up your restful resources by specifying the URL path and the HTTP verb.
00:10:28.000 You can associate different requests with a Lambda function, making it very intuitive.
00:10:34.300 Lastly, for CloudWatch Schedule events, you specify a fixed rate, like every 5 minutes.
00:10:41.500 Then you provide the Lambda function as a target, confirming all steps through the interface.
00:10:48.000 In summary, we’ve covered Lambda functions, API Gateway, and CloudWatch scheduled events.
00:10:55.000 Most people prefer to use a configuration management tool for serverless applications.
00:11:01.000 Writing Lambda functions in YAML is common, but I find it less satisfying than writing Ruby.
00:11:07.200 It feels reminiscent of Java development back in the 1990s, where config files were heavily used.
00:11:13.500 So, I wanted to create Jets to solve this problem.
00:11:20.000 Let’s dive into some code examples to see what Jets looks like.
00:11:26.000 Here’s a simple Jets function defined in the app functions folder.
00:11:31.000 It looks like a typical Ruby Lambda function, though not much is happening.
00:11:36.500 However, Jets provides a valuable structure with additional constructs that enhance functionality.
00:11:43.000 For example, in a Jets controller, methods can transform into Lambda functions.
00:11:50.000 If you have public methods in the controller, Jets converts those into Lambda functions.
00:11:57.000 You also have helper methods for functionality like rendering JSON, XML, or HTML.
00:12:03.500 Additionally, the parameters are accessible in a simplified format for easier handling.
00:12:10.000 When using puts in this environment, it logs data to CloudWatch.
00:12:15.000 Next, the routes file in Jets looks similar to traditional routing setups.
00:12:21.000 You define GETs and POSTs, just like you would in a normal Rails application.
00:12:27.000 This translates directly into API Gateway resources.
00:12:33.000 In Jets, you can also define background jobs for your application.
00:12:39.000 Implementing a background job is essential to avoid blocking web requests.
00:12:46.000 You can declare jobs that run periodically to handle tasks asynchronously.
00:12:53.000 These jobs get translated to scheduled event rules in CloudWatch.
00:12:59.000 The Ruby methods transform into Lambda functions, and the routes file corresponds to API Gateway resources.
00:13:05.000 There’s a `jets new` command that gets you started with different modes of operation.
00:13:10.000 The default mode is HTML CRUD, while you can also use API modes for lightweight setups.
00:13:17.000 If you only need a couple of Lambda functions, job mode is ideal for a lightweight structure.
00:13:24.000 With Jets, you just need a few commands to set up your application’s architecture.
00:13:30.000 For an app using an RDS database, the structure includes essential folders like app, controllers, models, and views.
00:13:36.000 The project helps maintain traditional MVC components while working in a serverless environment.
00:13:42.000 Once structure is set up, you can deploy the application quickly using just a few commands.
00:13:50.000 Now, let's take a look at some generated code.
00:13:56.000 Here is an example of the post controller with seven HTTP method actions.
00:14:03.000 This controller uses ActiveRecord for model management and connects to the database seamlessly.
00:14:09.000 Let's run a server locally to test the functionality before deploying.
00:14:15.000 Local testing is essential to ensure that everything works smoothly.
00:14:21.000 You can explore the routes and views that are generated for your application.
00:14:27.000 This approach allows immediate feedback as you work on your application.
00:14:34.000 Once you’ve tested everything locally, you can deploy with confidence.
00:14:40.000 Let’s return to the slides before wrapping up.
00:14:47.000 We covered the AWS API architecture, focusing on setting up endpoints and Lambda functions.
00:14:53.000 The conventional wisdom for serverless development emphasizes minimal canceling.
00:14:59.000 Now, let’s review the Jets components one more time.
00:15:06.000 Ruby methods translate into Lambda functions, while routing files go to API Gateway.
00:15:12.000 Jobs are scheduled and transformed into CloudWatch event rules.
00:15:19.000 The Jets framework greatly simplifies the serverless development process.
00:15:25.000 Let’s consider a common problem: YAML versus Ruby code.
00:15:32.000 While YAML can be lengthy, Ruby keeps your code concise and expressive.
00:15:39.000 As serverless technology matures, it’s crucial to leverage the power of code.
00:15:44.000 There are various integrations supported in the serverless ecosystem.
00:15:50.000 For instance, connecting AWS services like SQS, SNS, and Kinesis enhances functionality.
00:15:56.000 You can create automated workflows that respond dynamically to user actions.
00:16:03.000 For example, a modified security group can trigger a Lambda function that automatically adjusts permissions.
00:16:10.000 The IoT aspect of AWS opens up countless possibilities, allowing devices to connect seamlessly.
00:16:16.000 You can track temperature readings from devices, sending that data to the cloud.
00:16:25.000 For image processing, triggering functions when images are uploaded can automate workflows.
00:16:31.750 Job functions schedule tasks, such as backing up Route 53 records, at defined intervals.
00:16:38.000 Lastly, the essential Jets resource model allows you to transform code intuitively.
00:16:44.000 All the paths in Jets lead to resources, enabling easy customization.
00:16:51.500 Jets also features local server testing with a user-friendly interface.
00:16:57.500 Wrapper commands make it easier to interact with AWS in a streamlined way.
00:17:04.000 Furthermore, both relational databases and DynamoDB are supported for data management.
00:17:11.000 User permissions can be controlled using policies, making it flexible.
00:17:17.500 As we see improvements, functionality expands significantly, impacting development practices.
00:17:25.500 In summary, Jets simplifies Ruby serverless application development, making it user-friendly.
00:17:32.000 The future is promising with serverless solutions leading the way for developers.
00:17:39.000 Thank you very much for your time, and I'll be around for any questions!
Explore all talks recorded at Balkan Ruby 2019
+4