Google Cloud has a number of options to run your code. We'll focus on three serverless platforms: Cloud Functions, App Engine, and Cloud Run, all of which automatically scale by traffic and bill by usage. The biggest difference between these platforms is the level of abstraction. We can deploy a function to Cloud Functions, an app to App Engine, or an app with a custom runtime (a Docker container) to Cloud Run.
The most abstract serverless hosting option is a function. It has no code except the core business logic of a specialized service. Two challenges in working with serverless functions include:
- Developing locally without a platform to convert requests to function calls
- Finding hosting alternatives when the infrastructure, runtime, or cost constraints of your platform are reached
Using a "Hello World" function with an international twist: "Hello Translate", we'll explore a new way to mitigate these challenges on Google Cloud.
Standalone Functions with the Functions Framework
Like all Google Cloud Functions runtimes, the Node.js v10 runtime supports direct HTTP triggers while removing the overhead of HTTP routing from developers. Under the hood this magic is done by the open source Node.js functions framework. The framework installs as a normal dependency for your function and encapsulates express.js to provide clean and standardized HTTP request handling.
Because it provides an HTTP server you can run your function as a localhost web service, or deploy it to any web hosting platform.
- Write business logic
- Add a Function Framework
- Deploy to a web host
Let's get to the code for "Hello Translate".
Writing a Function
Create a new npm
package and install the functions framework and the translate library:
npm init
npm install @google-cloud/functions-framework@1 @google-cloud/translate@5
(The @1
and @5
bits instruct npm
to retrieve specific major versions of the libraries. It makes the code in this post less timeless, but more likely to work as long as these versions are compatible with Google Cloud.)
Cook up the code for "Hello Translate!":
Before we're ready to deploy HelloTranslate, let's modify the package.json
to define a start script:
"scripts": {
"start": "functions-framework --target=helloTranslate"
}
When npm start
is run, the Node process will start a web server in the function framework package which is configured to use the target function above. This enables local development with no other special dependencies. The same mechanism will be used in Cloud Functions, App Engine, and Cloud Run.
Getting setup to work with Google Cloud
Set up a development environment and configure your project to support the "Hello Translate" function:
- Create or select a Google Cloud Project. Add it to your shell environment with
export PROJECT=[Your Project ID]
to streamline the commands below. - Install and authenticate with the Cloud SDK
- Enable the the Translate API:
gcloud services enable translate.googleapis.com
Testing on Cloud Functions
Start by confirming this is works as a Cloud Function, let's deploy it!
gcloud functions deploy helloTranslate \
--runtime=nodejs10 --region=us-central1 --trigger-http
Wait a couple minutes and we're ready to make a request. Use curl to ask for "Hello World!" in the default Spanish language:
curl https://us-central1-${PROJECT}.cloudfunctions.net/helloTranslate
Hola Mundo!
To learn more about how to use Cloud Functions, check out the HTTP Functions how-to.
Deploying a Function to App Engine
Now that we've confirmed the code works with Cloud Functions, let's see it work as an app on App Engine. App Engine allows more control over the instance scaling and behavior, and the requirement to deploy an HTTP server is met by the function framework. This means we can deploy code to App Engine without stopping for code changes.
Adapt Hello Translate to App Engine by following these steps:
1) Add an app.yaml
configuration file to declare the runtime:
runtime: nodejs10
2) Deploy the code
gcloud app deploy
3) Ask our production service for the latest translation of "Hello World!" in Yoruba:
curl https://${PROJECT}.appspot.com?lang=yo
Mo ki O Ile Aiye!
To learn more about how to use App Engine Standard, check out the Building an App Quickstart.
Deploying a Function to Cloud Run
Cloud Run is similar to App Engine in expecting a full HTTP app to be deployed. Unlike App Engine, Cloud Run is driven by containers. Cloud Run does not know if you are using javascript, java, or a web server written in BASH. Containers allow the developer to customize the runtime environment.
Adapt Hello Translate to Cloud Run by following these steps:
1) Add a Dockerfile. Copy the Node.js Dockerfile from the Cloud Run quickstart. Here's a streamlined copy for quick reading:
2) Build the Container.
gcloud builds submit --tag=gcr.io/${PROJECT}/hello-translate
3) Deploy the service.
gcloud run deploy hello-translate \
--image=gcr.io/${PROJECT}/hello-translate
4) Ask our production service for the latest translation of "Hello World!" in Japanese:
curl https://hello-translate-j6jxwetqdq-uc.a.run.app?lang=ja
"こんにちは世界"
To learn more about how to use Cloud Run, check out the Build and Deploy Quickstart.
Helpful Abstraction!
The function framework is a good case of an abstraction. Code that makes sense to deploy as a function doesn't need much customization in HTTP handling, so why include the boilerplate anywhere that code is hosted? With an open source package, your functions-that-are-services code is more portable across compute platforms.
If your function is chafing at the runtime or concurrency limitations of Cloud Functions, consider using a Functions Framework to migrate your service to another hosting option such as Cloud Run. With a little more work, you can even bring over event-driven functions by configuring Pub/Sub push subscriptions.
Read Onward
For an example application using a Functions Framework to be simultaneously deployable to Cloud Functions and Cloud Run, check out Grant Timmerman's Pizza Map sample.
Top comments (0)