Google App Engine has an upper limit on how much data you can put into a task – a maximum of 100 KB. This includes everything within an individual task such as parameters, payload, the request URL, etc.
To get around this error, store any large pieces of information within an entity in the datastore. You can then pass the entity’s ID as a task parameter and pull out the entity’s data during task processing.
One of the best parts of hosting with App Engine is the free geolocation service it provides. Every incoming request has special AppEngine location headers added to it.
For instance, here’s how to find out the user’s city (req is the servlet’s HttpServletRequest object):
String city = req.getHeader("X-AppEngine-City");
Other geolocation information is available as well: the user’s country (X-AppEngine-Country), the region of that country (X-AppEngine-Region), and the nearest city’s latitude and longitude (X-AppEngine-CityLatLong).
Google’s Compute Engine just released into General Availability, and I’ve been testing it out the last couple of days.
The one thing that blows me away is how reliably fast even the low-end instances are. I provisioned and set up a f1-micro instance – it runs great and quite consistently. That’s in sharp contrast to Amazon’s micro instance which is limited to “bursty” processing; there are spikes where processing goes quickly, then the CPU gets throttled and the instance grinds to a near-halt.
I’m considering building a mail app on top of GCE – so far, everything looks great. GCE even allows inbound SMTP connections (although unfortunately no outbound SMTP connections).
I recently purchased a .IO domain name from nic.io, and immediately set about configuring it for Google App Engine. I was surprised to find out that nic.io doesn’t provide customizable DNS – you can’t set CNAMES, TXT or MX records. The only options provided are to set your own nameservers, or forward the domain to another web site.
Fortunately I have a spare GoDaddy account, and they offer free DNS services even for domains not hosted with them. Here’s how I configured nameservers for my .IO domain:
First, go to DNS Manager:
Select Off-site > Add Off-site:
Type in your .IO domain:
Copy the provided nameservers to your clipboard, and press finish:
Paste the nameservers into the nic.io administration page:
Wait 24 hours for the changes to propagate, and you’re done!
Google App Engine’s datastore is one of the most underrated parts of the service. Having a relatively cheap (in some cases free) use of a fast, reliable NoSQL store is a terrific deal, especially since most developers are only experienced with SQL databases.
With that said the App Engine datastore can get expensive quickly, especially if it’s being used inefficiently. One of my favorite illustrations of this point is this article. Here’s what I do to optimize my datastore use:
- Use .setUnindexedProperty. To set a property on an Entity you call entity.setProperty(key, value). But in the background App Engine is building an index (perhaps multiple indexes) to allow searches on that property. These index builds can get expensive very quickly. If you don’t need to search on a property, use setUnindexedProperty. This informs App Engine that the application will not be searching on that property, so don’t build an index.
- Cache data in memcache. Whenever you make a datastore request, copy the returned results into memcache. Then if you need to make the same request, try pulling the data from memcache before querying the datastore again. Memcache use is free so access it before the datastore. Some datastore abstractions – such as Objectify – do this automatically.
- If this is a high-traffic app, consider using a backend. A high-memory backend can hold a large amount of data in RAM, and you can transfer data to/from other instances by using URLFetch. As a bonus this technique can be faster than querying entities from the datastore.
- Turn off AppStats. If you have AppStats enabled, turn if off for some speed gains. AppStats stores its data in memcache which may cause some of your data to be evicted, causing increased datastore queries and an increased datastore bill.
Today I answered a question about how to create a folder in Google Drive . The answer is simple: Google Drive considers a folder to be simply another file, so to create a folder you use the same API call as creating a file, except that you pass in a MIME type of application/vnd.google-apps.folder.
It’s a pretty straightforward answer, but it started me thinking about the nature of folders and Google. It’s interesting that Google Drive supports folders at all, considering that another famous Google service – Gmail – doesn’t support folders at all. Instead, it has labels.
In Gmail, you can create as many labels as you want, and apply any number of them to an email. Labels are similar to folders: they enable users to categorize and easily search for files – the only thing missing is the hierarchical pattern that folders enable. Which leads me back to Google Drive: I wonder how folders are internally represented within the Google Drive system. Based on the API, it looks like folders are considered a special case of files.
But if Drive can handle folders as simply a special file, why doesn’t Gmail support folders as well? Is it simply that Gmail and Drive are separate codebases, or that Google feels that labels are a better categorizing scheme than folders?
It’s always interesting to think about Google’s architecture and how different services have vastly different builds and APIs.
One of the strengths of Go is the ability to return multiple values from a function. As a long-time Java programmer I’ve envied languages with muttiple returns for a long time. Here’s a quick summary of the feature:
Quick example: to return multiple values, use the classic return statement:
return value1, value2
And to get those return values from a function, you can write:
var1, var2 := someMultipleReturnFunction()
The great thing about this system is that you can ignore a return value if you don’t need it. For example, if you need to skip the first return value:
_, var2 := someMultipleReturnFunction()
Which brings me to the original reason for this blog post. I was writing a Go application, when a build failed due to the error not enough arguments to return. The problem was that I had multiple return statements within a function, and one of the statements declared only one return value, instead of the two return values that the function declared.
The easy fix? Simply declare nil to pad out the “missing” return value. So the return statement became:
return var1, nil
Easy, quick, and painless.
I’m in the middle of writing a Java application on App Engine to receive mail, and I decided to look up on how to do it in Go. It’s shockingly easy, just a few lines of code (r represents http.Request):
c := appengine.NewContext(r)
msg, err := mail.ReadMessage(r.Body)
And that’s it. You can extract headers and the mail message body from the Message struct. It’s quite pleasant to use, and surprisingly fast at parsing email.