Why Serverless?

June 28, 2017 0 Comments

Why Serverless?

 

 

Like most developers I know, I'm fairly jaded when it comes to the "next big thing." I've been in development, professionally, for over twenty years, and while I've seen a heck of a lot of incredible improvement in my time, I've also seen my fair share of fads that come and go. Up until somewhat recently, I was pretty dismissive of the serverless trend. Most of all the name annoyed me. I mean, "cloud" is a bit imaginative, but "serverless" is the exact opposite of what's actually going on.

But a few months ago I had some time and decided to look into this "new fad", and I must say, I've come away a changed person. No, serverless is not the solution to everything – not even close – but when I look back at the history of my development, it sure as heck would have been a solution for a good portion of it.

In this article, I want to explain what serverless is, why I think it is an important new development, and where I think it will be the most impactful. This article will not focus on any one platform (my own experience is with Apache OpenWhisk), but rather keep things at a mostly generic level.

As always, I'd love hear what you think, especially if you disagree with me, so please leave some comments below!

What is Serverless?

Let's begin with a basic definition. Since we know a computer is involved somehow, what exactly does it mean to be serverless?

"In essence, serverless means being able to deploy your code without worrying about a server."

Ok, so I'm hoping at least some of you are rolling your eyes at that. Let's consider a practical example of what this means. I want to deploy a system that lets me retrieve a list of cats from a database and render it out in JSON. Here's an incredibly simple implementation of this for Node:

var express = require('express'); var app = express(); app.get('/cats', (req, res) => { //go get my cats let cats = ["Luna","Robin","Cracker","Pig"]; res.json(cats); }); app.set('port', process.env.PORT || 3000); app.listen(app.get('port'), () => { console.log('Express running on http://localhost:' + app.get('port')); });

Now I realize that it's somewhat overkill to load up Express just for a simple API, but focus instead of what's going on here:

  • First, I need a way to set up and handle a route so that I know when to display cats. In other words, I need to know if /cats was requested instead of something like /dogs. I don't have a dogs API in there, but the process to add that would be twofold. First I write the business logic, then I setup the routing.
  • I have to fire up a web server in order to handle those requests. Express makes that trivial, but I still have to do it.
  • I have to work with a request and a response to handle client API calls. Again, Express makes this easy, but right now my logic is intimately tied to HTTP.
  • Ok, so all in all, not bad. I can get up and running in minutes. But then I need to deploy it.

  • First I find a host. Luckily Node hosting is a dime a dozen. IBM (my employer) has Bluemix. There's Now by Zeit. There's numerous other companies that let me deploy my Node code and have it up and running in minutes. I'm old enough to remember having to fax a request to a web hosting company to get a box setup that I could RDP to, install software, and then have my site up and running in a few days.

  • As part of this process, I have to think about my app usage and make some choices about CPU, memory, etc. I also have to figure out scaling. How does my platform allow me to scale up when load hits?

Still not *too *bad. The Cloud, in general, made a lot of this easier. I can have a new machine deployed in EC2 in seconds, a new Node server in Bluemix in the same time. But the common theme here is the server. I'm still thinking about it. I'm still setting it up (easy or not). It's still something I have to keep in mind.

Now let's flip it around and go serverless. I have the same use case – I want an API available to return a list of cats. Here's my code.

function main(args) { //go get my cats let cats = ["Luna", "Robin", "Cracker", "Pig"]; return { cats: cats}; }

And that's it. The code to implement my business logic is the only thing I have to worry about.

Notice that my function takes an args parameter. This is how OpenWhisk handles arguments. That may be different in Lambda or Google Cloud Functions, so there is some code that is a bit dependent on the platform.

Deploying this simply means running a command line to add it to OpenWhisk – similar routines are available for other serverless platforms. So in the end…

  • I worry about the business logic (get those cats!)
  • I don't worry about routing – my platform will tell me how Cats are available
  • I'm not tied to an HTTP model anymore. I can use this routine as a scheduled task run daily by the serverless platform and not even consider the web. Or I could do that and use it for a web site.

In the end, I'm still doing the same thing – making my business logic available, but I'm not worrying about a number of other things related to making the logic accessible via the web. In other words, I'm not worried about the server.

Serverless becomes, not the absence of servers, but the concern of the provider. If there's one thing I've learned in my time in tech, I'm far happier when I have to worry about fewer things. In general, my only concern now is that my cat routine works.

All of this comes with one more, major, benefit – cost. Even with a lightweight Node server, I'm still running it 24 hours a day, 7 days a week, on the off chance that someone, anyone, may actually use it. While I know some of us work on sites that are pounded every second of the day, a large amount of the web is sitting there idle waiting for a request. And of course, while that server is sitting there idle (probably being attacked by bored script kiddies), I'm paying money.

"It's the functions, stupid!"

Another term for serverless, and one I like a bit better, is "Function as a Service" (FaaS). This boils serverless down to what you typically end up building – ad hoc functions. Separating your code into functions is, of course, nothing new. Where serverless puts a spin on this is two fold:

First – everything you write is a function. 100% of your code is standalone and composable. This truly opens up the ability to mix and match your code to create new services.

Here's a practical example. IBM Watson has a "Tone Analysis" service. Basically pass it some text and Watson analyzes it to tell you what the writer was feeling. I was able to build a function to interact with this rather easily. Then I remembered I had built a simple RSS reader. I create a new service by simply combining the two: Get the emotional values of a person based on their RSS feed. Then I decided – why not quickly build a function to get the last set of tweets from a user. I did that and then built yet another service: Get the emotional values of a person based on their Twitter feed.

The second interesting aspect is that these functions can be built in entirely different languages. If something needs code that's better suited to Java, or Swift, then a function could be written in that language. And as described above, I can easily mix up a Java function with a Node function to create an entirely new service.

When Not to Serverless

As excited as I am about serverless, it obviously is not the One True Answer to every development platform. I honestly see it as being incredibly useful for many cases, but it's definitely not going to solve every every problem. Here's a few things that you may want to consider before going serverless.

  • Serverless is stateless. While you can definitely do persistence with traditional databases or NoSQL solutions, every time your function runs it's fired up, does it's thing, and then shut down. A serverless provider may keep it running for a short time – so a popular API will stay "warm" and you can use that to your advantage, but in general your code has to assume it knows nothing when it starts up.
  • Since your code is typically written in standalone, atomic, functions, handling "flow" can be problematic. OpenWhisk has a concept of sequences, basically a new service built out of the combination of multiple functions. What's not supported (yet) is the concept of an API built out functions and complex logic. Something like: Begin with A. If the result is X, do B, otherwise do C. Then branch out to 4 other functions based on the result of B or C, and maybe end if C realizes the entire job is done. And then do D. And then maybe E or F. And so on and so on.
  • Moving your code from one provider to another may be problematic. The code I shared above works for OpenWhisk, but would not for Lambda. Of course, solutions like Serverless (yes, a framework named for a technology, not confusing at all, see more at serverless.com) provide an abstraction layer to make this easier though.
  • Testing can be somewhat difficult. Since the serverless provider handles so much of process, your testing has to focus on business logic only. I've built ways to run my OpenWhisk code locally, but that isn't the same as a proper testing framework.
  • Monitoring may be an issue as well. I've blogged about OpenWhisk and it's current monitoring system, and while it's OK, it has some room for improvement. I may not be worried about a server going down, but I'm still concerned with how well my code is performing and if 3rd party APIs are causing any issues.

Of course, the final thing to remember is that this is still an incredibly new space. There's bound to be a lot of best practices learned the good old fashioned way – after completely screwing up.

The Choices

Currently serverless providers can be grouped into two main categories – general frameworks and targeted ones. The "general" ones pretty much come from names you expect:

There's more of course, but the new trend is what I call "targeted" serverless platforms. These are platforms not necessarily built for anything and everything, but rather a platform that uses serverless as a way of letting you extend existing services. An original, early example of this was the late great Parse. Their core focus was on APIs related to data CRUD. But they realized there were times when it made sense to apply logic on the server before returning data. They supported the ability to write JavaScript and deploy it to their services. In this case, the "serverless" platform was specifically targeted to enhancing the existing APIs.

As a more current (i.e. not dead) example of this, last month Twilio announced support for serverless functions specifically meant to enhance people already using their service. Frankly I see this space as being much more interesting. You get the benefit of being "closer" to an existing service you're using as well as potential "add ons" and other benefits from running in the same space as your API provider.

But Wait – There's More…

So where can you go to learn more? Obviously you can start with one of the big choices I listed above. That will get you started. (I'm digging OpenWhisk and you can find a bunch of my blog postings on it) Finally, you can get a weekly newsletter of interesting serverless related articles by signing up for the Cooper Press newsletter, Serverless Status.


Tag cloud