At Belly we’re building a Service Oriented Architecture. There are a lot of benefits we get by building our applications in this way:
- We are able to scale services independently
- Services have a limited number of concerns
- We mitigate many scenarios that would create a single point of failure
- and many more…
We decided early on that it would be a big win if we could build all of our services on a single common platform. It would make it easy for developers to jump from one service to another, and we could share lots of code, tools and instrumentation across our apps.
So we built something we’re calling Napa.
All of our services are built as simple Ruby Rack applications using the Grape micro-framework and Unicorn. This combination seems to work really well, and we are able to achieve apps that are very lean and perform quite well. Some of these services process millions of requests per day without breaking a sweat.
Napa has 3 tenants:
- Application Standardization — we want all of our services to be as similar as possible so that any developer on the team can jump into an app and immediately know where things are and how they work.
- Developer Productivity — we want it to be easy to create a new service, test functionality and debug things when something goes wrong.
- Shared Functionality — we don’t want to have to reinvent the wheel in every service, so any common functionality should be abstracted to reusable libraries that have their own test suites and can be shared across many services.
To achieve these goals, we have a number of features in Napa, with more planned for the future.
For Application Standardization we have created a generator that will scaffold up a new service, similar to the way rails new works. So, with Napa installed, you can simply run
napa new your_project_name and a folder will be created with a handful of files and folders needed to get your app started. This is a huge with for standardization because, now, all of our services have the same folder structure, same common libraries and so on. It’s also a productivity win because a developer can spin up a new app in just a few seconds.
We also created a common logger so that all of our application logs are sent in the same format. This is nice because the developer doesn’t need to be concerned with formatting their logs and it also makes things easier when using something like Splunk.
Developer Productivity is always important, so we added a few simple things that make it very easy to work with these new apps.
ruby console— if you’re used to working in Rails you’ve probably become accustomed to the Rails console. Napa has a console too. You can run it by simply typing
ruby console. This will drop you into an IRB session within your application’s context. Just like in Rails. It’s awesome!
rake routes— another thing we brought over from Rails, this rake task allows you to quickly see the routes Grape has generated for your service
rake deploy— some simple rake task that hook into our Chef deployment process
As of the current release, our Shared Functionality is somewhat minimal, but more features are planned for release soon. Some of the current features are:
- The Logger Middleware (
Napa::Middleware::Logger) enables the standardized logging format we send to Splunk.
- The AppMonitor Middleware (
Napa::Middleware::AppMonitor) adds a
/healthendpoint to your app which we use as a standardized way to configure monitoring tools. Every service has it right away, so we never have to think about it when deploying a new service.
To find out more about Napa you can view the project on Github – https://github.com/bellycard/napa or install it with
gem install napa. Feel free to use it for your own projects, contribute features, or tell us what you like or don’t like.