2015年10月6日 星期二

Connect to Other Google Cloud Services in Google Compute Engine (Go Language)

    It has been discussing for a long time: Should I use Compute Engine or App Engine? Well, If you need full control on the system, it's definitely Compute Engine. But If you just want to build an application system, including dynamic web server, API server and database, for example, it would be pretty hard to choose between them. Although this article is not going to do some real comparison, the following may give you some concepts on the differences between the two platforms when it comes to building application systems.

    Connecting to other google cloud services within the App Engine is a piece of cake:
func handle(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)

    e1 := Employee{
        Name:     "Bekket McClane",
        Role:     "Engineer",
        HireDate: time.Now(),
    }

    key, err := datastore.Put(c, datastore.NewKey(c, "employee", "mshockwave", 0, nil), &e1)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    var e2 Employee
    if err = datastore.Get(c, key, &e2); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "Stored and retrieved the Employee named %q", e2.Name)
}

    All we need to do is instantiating a new context and call the straightforward Put and Get functions. Most of the google cloud service usages are as easy as this case, except the cloud storage, which we would mention the reason later.
    Let's look at the Compute Engine side. The Compute Engine, unlike App Engine, which is wrapped in a well managed runtime, accesses other google cloud service as if a normal client-side application. In another word, your machine need to handle all the OAuth2 flow with the google api client library. What's worse, there is no stable release of Go language SDK specific for cloud platform. But it's worth for a shot to use the github version of Go cloud platform SDK. Here is a simple datastore example(You can still use go get to fetch related libraries):

package storage

import (
 "golang.org/x/oauth2/google"
 "golang.org/x/net/context"
 "log"
 "google.golang.org/cloud/datastore"
 "google.golang.org/cloud"
)


var datastoreClient *datastore.Client
var ctx context.Context
func init(){

 ctx = context.Background()

 defaultTokenSource, err := google.DefaultTokenSource(ctx,
  datastore.ScopeDatastore,
  datastore.ScopeUserEmail,
 )
 if err != nil || defaultTokenSource == nil{
  log.Fatalf("Error getting google default token source")
  return
 }

 datastoreClient, err = datastore.NewClient(ctx, PROJECT_ID, cloud.WithTokenSource(defaultTokenSource))
 if err != nil {
  log.Fatalf("Error getting datastore client")
  return
 }
}

func GetDatastoreClient() *datastore.Client { return datastoreClient }
func GetDatastoreContext() context.Context { return ctx }

    Authorization part is always out first concern, the approach I used in the above snippet is the neatest in my opinion. Since the authorization way in the official go document use the json key file(you can retrieve one in your developer console) which is less portable. The key component works behind DefaultTokenSource is the gcloud utility in  Google Cloud SDK. It would set some environment variables holding authorization informations. Google do really well on this part since it not only keep you from handling the messy authorization flow, it also let you use the same code both in the cloud platform AND local development environment. So you really need to install the Google Cloud SDK no matter what kind of application you are building. There are other authorization methods which is in the google package of the official go oauth2 library.
    It seems that Google is going to move cloud platform related parts from its API client library to individual cloud platform library which is still under development so far. The similar situation happens on App Engine since they are trying to unify the libraries between App Engine and the new Managed VM. Some of the important parts, Blob service for example, are going to be deprecated. They want to remove most of the Blob service functions and migrate all file related operations to the cloud storage. Thus you can find that the usage of cloud storage service is different from other google cloud services due to the progressing migration and library integration with Managed VM.