Geosophic is a platform of online services for mobile games. It offers both user engagement features (such as leaderboards and achievements) and analytics.
In this talk I would like to share with you our experience building this platform with Grails with the goal to support a big load. I’ll focus on the system architecture, the problems we have found and how we are solving them.
Why Teams call analytics are critical to your entire business
Building a scalable API with Grails
1. Building a scalable API with
Grails
Greach – 2013-01-26
Tanausú Cerdeña
@chozero | @geosophers
2. What you can expect from this talk
• A story of an API creation on Grails.
• Decisions made and the reasons behind.
• Pitfalls.
• We’re learning as we go.
3. About me
• Tanausú Cerdeña (@chozero)
• Sysadmin background.
• Grails user for two years.
• Co-founder and CTO at Geosophic.
4. Let’s get some context first
Online services for mobile games:
• Gaming features: Leaderboards, player
matching…
• Data tracking: levels played, session duration…
• Monetization: Performance ad serving.
5. Let’s get some context first
Online services for mobile games:
• Gaming features: Leaderboards, player
matching…
• Data tracking: levels played, session duration…
• Monetization: Performance ad serving.
6. Why Grails?
1. Productivity. Geosophic started as
an MVP.
2. Java experience on the team.
3. It’s fun to use! (+15% developer
happiness).
7. Our development environment
• Grails 2.1.1 / Groovy 1.8.8
• STS / vim. Trying to move to Intellij (thanks
doomsday!!)
• Deployed to AWS (Elastic Beanstalk).
• Team of 3 developers:
• 1 backend, 1 frontend, 1 mobile
• Everyone touches everything.
8. Overview of architecture
Android iOS
SDK SDK
HTTP API Dashboard (Grails)
API Controllers Dashboard Controllers
Services
Domain Objects
MySQL Redis
12. API Design: URL schema
http://{baseURL}/{version}/{feature}/{item}/{action?}
http://api.geosophic.com/v1/leaderboards/leaderboard/nearest
http://api.geosophic.com/v1/leaderboards/score
http://api.geosophic.com/v1/track/event
13. API Design: Versioning options
In the URL path?
http://my.api.com/v1/endpoint
As a URL parameter?
http://my.api.com/endpoint??v=1
Custom HTTP Header?
Accept-Version: 1
Versioned media types?
Accept: application/vnd.myapp-v1+json
14. API Design: Versioning options
In the URL path?
http://my.api.com/v1/endpoint
As a URL parameter?
http://my.api.com/endpoint??v=1
Custom HTTP Header?
Accept-Version: 1
Versioned media types?
Accept: application/vnd.myapp-v1+json
15. API Design: Versioning issues
• Scarcity of resources to handle different
versions.
• Backwards compatibility?
• Our first client deployed, a week later, we
decided a change on the API.
• Mobile clients (apps) don’t update that often.
16. HTTP methods
Our API model doesn’t match perfectly with a CRUD
model so no fully REST API.
• GET: Retrieving info.
• Get a leaderboard
• POST: Submitting info.
• Send a score.
• Submit an event.
18. API Design: Response format
Only JSON. No XML
{
meta: {
apiVersion: “1.0.1”,
code: 400,
errorType: “User id required”,
msgs: []
},
response: {
// Content depends on endpoint
},
notifications: { // Future use }
}
20. Rendering response
render as JSON:
• We have a mix of domain classes and other
objects to render.
• Write custom JSON Marshaller for some
classes.
• Register them at BootStrap.groovy.
23. DRY in our API Controllers
We have some common code for all our API
endpoints:
• Authentication.
• API usage tracking.
• Common parameters validation.
28. API Design: Authentication
• (consumer key, consumer secret) per
client.
• Consumer key used to identify the
client (sent as a URL parameter).
• Consumer secret to sign the request.
• This is (sort of) 2-legged Oauth.
29. API Design: Authentication
• Some plugins implementing clients,
but no suitable (for us) server
implementation (maybe we didn’t look
deep enough?).
• Better to use SpringSecurity and
customize?
• We are feeling more confident and
want to contribute this.
30. API Design: Handling errors
• 400 handled by each Controller
• 500 handled by ErrorController
(mapped in UrlMappings.groovy)
36. Performance considerations
• No GSPs but JSON so quite fast.
• Asynchronous tracking helps.
• Difficult to cache (except for
leaderboards). We cache in the
service.
37. Some performance figures
• 1 EC2 small instance(1.7GB RAM)
• API + Services + Dashboard
• 90K users, 7K daily active.
• Throughput: ~ 75 rpm (peaks of 200)
• Server response time: ~ 160 ms
average
• Performance tests: up to 450 rpm
38. Bottlenecks
• Database: MySQL
• Redis for most read data:
• Gaming features (leaderboards)
• Evaluating metrics storage:
• Redis
• Cube (from Square)
39. Next steps
• Improve the API usage tracking.
• Spock.
• See what we can contribute (Auth? API
usage?)
• Looking for a nice log viewer solution