Chapter 9.  Building a Q&A Application for Google App Engine

Google App Engine gives developers a NoOps (short for No Operations, indicating that developers and engineers have no work to do in order to have their code running and available) way of deploying their applications, and Go has been officially supported as a language option for some years now. Google's architecture runs some of the biggest applications in the world, such as Google Search, Google Maps, and Gmail, among others, so is a pretty safe bet when it comes to deploying our own code.

Google App Engine allows you to write a Go application, add a few special configuration files, and deploy it to Google's servers, where it will be hosted and made available in a highly available, scalable, and elastic environment. Instances will automatically spin up to meet demand and tear down gracefully when they are no longer needed with a healthy free quota and preapproved budgets.

Along with running application instances, Google App Engine makes available a myriad of useful services, such as fast and high-scale data stores, search, memcache, and task queues. Transparent load balancing means you don't need to build and maintain additional software or hardware to ensure servers don't get overloaded and that requests are fulfilled quickly.

In this chapter, we will build the API backend for a question and answer service similar to Stack Overflow or Quora and deploy it to Google App Engine. In the process, we'll explore techniques, patterns, and practices that can be applied to all such applications, as well as dive deep into some of the more useful services available to our application.

Specifically, in this chapter, you will learn:

  • How to use the Google App Engine SDK for Go to build and test applications locally before deploying to the cloud
  • How to use app.yaml to configure your application
  • How Modules in Google App Engine let you independently manage the different components that make up your application
  • How the Google Cloud Datastore lets you persist and query data at scale
  • A sensible pattern for the modeling of data and working with keys in Google Cloud Datastore
  • How to use the Google App Engine Users API to authenticate people with Google accounts
  • A pattern to embed denormalized data into entities
  • How to ensure data integrity and build counters using transactions
  • Why maintaining a good line of sight in code helps improve maintainability
  • How to achieve simple HTTP routing without adding a dependency to a third-party package

The Google App Engine SDK for Go

In order to run and deploy Google App Engine applications, we must download and configure the Go SDK. Head over to https://cloud.google.com/appengine/downloads and download the latest Google App Engine SDK for Go for your computer. The ZIP file contains a folder called go_appengine, which you should place in an appropriate folder outside of your GOPATH, for example, in /Users/yourname/work/go_appengine.

Tip

It is possible that the names of these SDKs will change in the future; if that happens, ensure that you consult the project home page for notes pointing you in the right direction at https://github.com/matryer/goblueprints.

Next, you will need to add the go_appengine folder to your $PATH environment variable, much like what you did with the go folder when you first configured Go.

To test your installation, open a terminal and type this:

goapp version

You should see something like the following:

go version go1.6.1 (appengine-1.9.37) darwin/amd64

Note

The actual version of Go is likely to differ and is often a few months behind actual Go releases. This is because the Cloud Platform team at Google needs to do work on its end to support new releases of Go.

The goapp command is a drop-in replacement for the go command with a few additional subcommands; so you can do things like goapp test and goapp vet, for example.

Creating your application

In order to deploy an application to Google's servers, we must use the Google Cloud Platform Console to set it up. In a browser, go to https://console.cloud.google.com and sign in with your Google account. Look for the Create Project menu item, which often gets moved around as the console changes from time to time. If you already have some projects, click on a project name to open a submenu, and you'll find it in there.

Tip

If you can't find what you're looking for, just search Creating App Engine project and you'll find it.

When the New Project dialog box opens, you will be asked for a name for your application. You are free to call it whatever you like (for example, Answers), but note the Project ID that is generated for you; you will need to refer to this when you configure your app later. You can also click on Edit and specify your own ID, but know that the value must be globally unique, so you'll have to get creative when thinking one up. In this book, we will use answersapp as the application ID, but you won't be able to use that one since it has already been taken.

You may need to wait a minute or two for your project to get created; there's no need to watch the page you can continue and check back later.

App Engine applications are Go packages

Now that the Google App Engine SDK for Go is configured and our application has been created, we can start building it.

In Google App Engine, an application is just a normal Go package with an init function that registers handlers via the http.Handle or http.HandleFunc functions. It does not need to be the main package like normal tools.

Create a new folder (somewhere inside your GOPATH folder) called answersapp/api and add the following main.go file:

package api 
import ( 
  "io" 
  "net/http" 
) 
func init() { 
  http.HandleFunc("/", handleHello) 
} 
func handleHello(w http.ResponseWriter, r *http.Request) { 
  io.WriteString(w, "Hello from App Engine") 
} 

You will be familiar with most of this by now, but note that there is no ListenAndServe call, and the handlers are set inside the init function rather than main. We are going to handle every request with our simple handleHello function, which will just write a welcoming string.

The app.yaml file

In order to turn our simple Go package into a Google App Engine application, we must add a special configuration file called app.yaml. The file will go at the root of the application or module, so create it inside the answersapp/api folder with the following contents:

application: YOUR_APPLICATION_ID_HERE 
version: 1 
runtime: go 
api_version: go1 
handlers: 
- url: /.* 
  script: _go_app 

The file is a simple human-(and machine) readable configuration file in YAML (Yet Another Markup Language format refer to yaml.org for more details). The following table describes each property:

Property

Description

application

The application ID (copied and pasted from when you created your project).

version

Your application version number you can deploy multiple versions and even split traffic between them to test new features, among other things. We'll just stick with version 1 for now.

runtime

The name of the runtime that will execute your application. Since this is a Go book and since we're building a Go application, we'll use go.

api_version

The go1 api version is the runtime version supported by Google; you can imagine that this could be go2 in the future.

handlers

A selection of configured URL mappings. In our case, everything will be mapped to the special _go_app script, but you can also specify static files and folders here.

Running simple applications locally

Before we deploy our application, it makes sense to test it locally. We can do this using the App Engine SDK we downloaded earlier.

Navigate to your answersapp/api folder and run the following command in a terminal:

goapp serve

You should see the following output:

Running simple applications locally

This indicates that an API server is running locally on port :56443, an admin server is running on :8000, and our application (the module default) is now serving at localhost:8080, so let's hit that one in a browser.

Running simple applications locally

As you can see by the Hello from App Engine response, our application is running locally. Navigate to the admin server by changing the port from :8080 to :8000.

Running simple applications locally

The preceding screenshot shows the web portal that we can use to interrogate the internals of our application, including viewing running instances, inspecting the data store, managing task queues, and more.

Deploying simple applications to Google App Engine

To truly understand the power of Google App Engine's NoOps promise, we are going to deploy this simple application to the cloud. Back in the terminal, stop the server by hitting Ctrl+C and run the following command:

goapp deploy

Your application will be packaged and uploaded to Google's servers. Once it's finished, you should see something like the following:

Completed update of app: theanswersapp, version: 1

It really is as simple as that.

You can prove this by navigating to the endpoint you get for free with every Google App Engine application, remembering to replace the application ID with your own: https://YOUR_APPLICATION_ID_HERE.appspot.com/.

You will see the same output as earlier (the font may render differently since Google's servers will make assumptions about the content type that the local dev server doesn't).

Note

The application is being served over HTTP/2 and is already capable of pretty massive scale, and all we did was write a config file and a few lines of code.

Modules in Google App Engine

A module is a Go package that can be versioned, updated, and managed independently. An app might have a single module, or it can be made up of many modules, each distinct but part of the same application with access to the same data and services. An application must have a default module even if it doesn't do much.

Our application will be made up of the following modules:

Description

The module name

The obligatory default module

default

An API package delivering RESTful JSON

api

A static website serving HTML, CSS, and JavaScript that makes AJAX calls to the API module

web

Each module will be a Go package and will, therefore, live inside its own folder.

Let's reorganize our project into modules by creating a new folder alongside the api folder called default.

We are not going to make our default module do anything other than use it for configuration, as we want our other modules to do all the meaningful work. But if we leave this folder empty, the Google App Engine SDK will complain that it has nothing to build.

Inside the default folder, add the following placeholder main.go file:

package defaultmodule 
func init() {} 

This file does nothing except allow our default module to exist

Note

It would have been nice for our package names to match the folders, but default is a reserved keyword in Go, so we have a good reason to break that rule.

The other module in our application will be called web, so create another folder alongside the api and default folders called web. In this chapter, we are only going to build the API for our application and cheat by downloading the web module.

Head over to the project home page at https://github.com/matryer/goblueprints, access the content for Second Edition, and look for the download link for the web components for Chapter 9, Building a Q&A Application for Google App Engine in the Downloads section of the README file. The ZIP file contains the source files for the web component, which should be unzipped and placed inside the web folder.

Now, our application structure should look like this:

/answersapp/api 
/answersapp/default 
/answersapp/web 

Specifying modules

To specify which module our api package will become, we must add a property to the app.yaml inside our api folder. Update it to include the module property:

application: YOUR_APPLICATION_ID_HERE 
version: 1 
runtime: go 
module: api 
api_version: go1 
handlers: 
- url: /.* 
  script: _go_app 

Since our default module will need to be deployed as well, we also need to add an app.yaml configuration file to it. Duplicate the api/app.yaml file inside default/app.yaml, changing the module to default:

application: YOUR_APPLICATION_ID_HERE 
version: 1 
runtime: go 
module: default 
api_version: go1 
handlers: 
- url: /.* 
  script: _go_app 

Routing to modules with dispatch.yaml

In order to route traffic appropriately to our modules, we will create another configuration file called dispatch.yaml, which will let us map URL patterns to the modules.

We want all traffic beginning with the /api/ path to be routed to the api module and everything else to the web module. As mentioned earlier, we won't expect our default module to handle any traffic, but it will have more utility later.

In the answersapp folder (alongside our module folders not inside any of the module folders), create a new file called dispatch.yaml with the following contents:

application: YOUR_APPLICATION_ID_HERE 
dispatch: 
  - url: "*/api/*" 
    module: api 
  - url: "*/*" 
    module: web 

The same application property tells the Google App Engine SDK for Go which application we are referring to, and the dispatch section routes URLs to modules.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.172.200