Transcript
Page 1: Utopia Kingdoms scaling case. From 4 users to 50.000+

● scaling case. From 4 users to 90k+●

● Jaime Buelta● Soft. Developer at

Page 2: Utopia Kingdoms scaling case. From 4 users to 50.000+

The Game

Page 3: Utopia Kingdoms scaling case. From 4 users to 50.000+

Get image from game

Page 4: Utopia Kingdoms scaling case. From 4 users to 50.000+

Utopia Kingdoms

● Fantasy strategy game● Build your own Kingdom● Create armies and attack other Kingdoms● Join other Kingdoms in an Alliance● Manage resources● Available in Facebook and Kongregate

http://www.facebook.com/UtopiaKigdomsGamehttp://www.kongregate.com/games/JoltOnline/utopia-kingdoms

Page 5: Utopia Kingdoms scaling case. From 4 users to 50.000+

Technology stack

Page 6: Utopia Kingdoms scaling case. From 4 users to 50.000+

Technology Stack - Backend

PythonCherrypy framework

Amazon SimpleDBLinux in Amazon EC2

Page 7: Utopia Kingdoms scaling case. From 4 users to 50.000+

Stack of technologies - Frontend

HTML( generated by Genshi templates)

jQuery

Page 8: Utopia Kingdoms scaling case. From 4 users to 50.000+

Stack of technologies - Frontend

HTML( generated by Genshi templates)

jQuery

Page 9: Utopia Kingdoms scaling case. From 4 users to 50.000+

Some points of interest(will discuss them later)

● Your resources (population, gold, food, etc) grows with time

● You actions (build something, attack a player) typically takes some time

● Players are ranked against the rest● You can add friends and enemies

Page 10: Utopia Kingdoms scaling case. From 4 users to 50.000+

Do not guess

Measure

Page 11: Utopia Kingdoms scaling case. From 4 users to 50.000+

Measurement tools

● OS tools● Task manager (top)● IO Monitor (iostat)

● Monitoring tools (Munin, Nagios)

● Logs● Needs to find a good compromise detailed/relevance

● Profiling

Page 12: Utopia Kingdoms scaling case. From 4 users to 50.000+

You've got to love profiling

● Generate profiles with cProfile module

Profile whole application with

python -m cProfile -o file.prof my_app.py

(not very useful in a web app)

● If you're using a framework, profile only your functions to reduce noise

Page 13: Utopia Kingdoms scaling case. From 4 users to 50.000+

Profile decorator (example)

def profile_this(func):

import cProfile

prof = cProfile.Profile()

retval = prof.runcall(func)

filename = 'profile-{ts}.prof'.format(time.time())

prof.dumpstats(filename)

return retval

Page 14: Utopia Kingdoms scaling case. From 4 users to 50.000+

Analyzing profile

● gprof2dot● Using dot, convert to graph

gprof2dot -f pstats file.prof | dot -Tpng -o file.png

● Good for workflows

● RunSnakeRun● Good for cumulative times

Page 15: Utopia Kingdoms scaling case. From 4 users to 50.000+

Example of RunSnakeRunRAZR

Page 16: Utopia Kingdoms scaling case. From 4 users to 50.000+

Example of gprof2dot

Page 17: Utopia Kingdoms scaling case. From 4 users to 50.000+

The power of cache

Page 18: Utopia Kingdoms scaling case. From 4 users to 50.000+

All static should be out of python

● Use a good web server to serve all static content (Static HTML, CSS, JavaScript code)

● Some options● Apache● Nginx● Cherokee● Amazon S3

Page 19: Utopia Kingdoms scaling case. From 4 users to 50.000+

Use memcached(and share the cache between your servers)

Page 20: Utopia Kingdoms scaling case. From 4 users to 50.000+

Example

● Asking for friends/enemies to DB● Costly request in SimpleDB (using SQL statement)

● On each request● Cache the friends on memcache for 1 hour● Invalidate the cache if adding/removing

friends or enemies

Page 21: Utopia Kingdoms scaling case. From 4 users to 50.000+

Caching caveats

● Cache only after knowing there is a problem● Do not trust in cache for storage● Take a look on size of cached data● Choosing a good cache time can be difcult /

Invalidate cache can be complex● Some data is too dynamic to be cached

Page 22: Utopia Kingdoms scaling case. From 4 users to 50.000+

Caching is not just memcached

● More options available:● Get on memory on start● File cache● Cache client side

Page 23: Utopia Kingdoms scaling case. From 4 users to 50.000+

Parse templates just once

● The template rendering modules have options to parse the templates just once

● Be sure to activate it in production● In development, you'll most likely want to

parse them each time

● Same apply to regex, specially complex ones

Page 24: Utopia Kingdoms scaling case. From 4 users to 50.000+

More problems

Page 25: Utopia Kingdoms scaling case. From 4 users to 50.000+

Rankings

● Sort players on the DB is slow when you grow the number of players

● Solution:● Independent ranking server (operates just in

memory)● Works using binary trees● Small Django project, communicates using xmlrpc

● Inconvenient:● Data is not persistent, if the rankings server goes

down, needs time to reconstruct the rankings

Page 26: Utopia Kingdoms scaling case. From 4 users to 50.000+

Database pulling - Resources

● There was a process just taking care of the growth of resources.● It goes element by element, and increasing the

values● It pulls the DB constantly, even when the user has

their values to maximum● Increment the resources of a user just the next

time is accessed (by himself or by others)● No usage of DB when the user is not in use● The request already reads from DB the user

Page 27: Utopia Kingdoms scaling case. From 4 users to 50.000+

Database pulling - Actions

● Lots of actions are delayed. Recruit a unit, buildings, raids...

● A process check each user if an action has to be done NOW.● Tons of reads just to check “not now”● Great delay in some actions, as they are not

executed in time

Page 28: Utopia Kingdoms scaling case. From 4 users to 50.000+

Database pulling - Actions

● Implement a queue to execute the actions at the proper time:● Beanstalk (allows deferred extraction)● A process listen to this queue and performs the

action, independently from request servers.● The process can be launched in a diferent

machine.● Multiple process can extract actions faster.

Page 29: Utopia Kingdoms scaling case. From 4 users to 50.000+

DataBase Issues

Page 30: Utopia Kingdoms scaling case. From 4 users to 50.000+

Amazon SimpleDB

● Key – Value storage● Capable of SQL queries● Store a dictionary (schemaless, multiple

columns)● All the values are strings● Access through boto module● Pay per use

Page 31: Utopia Kingdoms scaling case. From 4 users to 50.000+

Problems with SimpleDB

● Lack of control● Can't use local copy

– In development, you must access Amazon servers (slow and costly)

● Can't backup except manually● Can't analyze or change DB (e.g. can't define

indexes)● Can't monitor DB

Page 32: Utopia Kingdoms scaling case. From 4 users to 50.000+

Problems with SimpleDB

● Bad tool support● Slow and high variability (especially on SQL

queries)● Sometime, the queries just timeout and had to be

repeated.

Page 33: Utopia Kingdoms scaling case. From 4 users to 50.000+

Migrate to MongoDB

Page 34: Utopia Kingdoms scaling case. From 4 users to 50.000+

MongoDB

● NoSQL● Schemaless● Fast● Allow complex queries● Retain control (backups, measure queries, etc)● Previous experience using it from ChampMan

Page 35: Utopia Kingdoms scaling case. From 4 users to 50.000+

Requisites of the migration

● Low-level approach● Objects are basically dictionaries● Be able to save dirty fields (avoid saving

unchanged values)● Log queries to measure performance

Page 36: Utopia Kingdoms scaling case. From 4 users to 50.000+

MongoSpell● Thin wrap over pymongo● Objects are just dictionary-like elements● Minimal schema● Fast!● Able to log queries● It will probably be released soon as Open

Source

Page 37: Utopia Kingdoms scaling case. From 4 users to 50.000+

Definition of collections

class Spell(Document):

collection_name = 'spells'

needed_fields = ['name',

'cost',

'duration']

optional_fields = [

'elemental',

]

activate_dirty_fields = True

indexes = ['name__unique', 'cost']

Page 38: Utopia Kingdoms scaling case. From 4 users to 50.000+

Querying from DB

Spell.get_from_db(name='fireball')

Spell.filter()

Spell.filter(sort='name')

Spell.filter(name__in=['fireball', 'magic missile'])

Spell.filter(elemental__fire__gt=2)

Spell.filter(duration__gt=2,

cost=3, hint='cost')

Spell.filter(name='fireball', only='cost')

Page 39: Utopia Kingdoms scaling case. From 4 users to 50.000+

Some features

● Dirty fields● No type checks● Query logs● 10x faster than SimpleDB!!!

Page 40: Utopia Kingdoms scaling case. From 4 users to 50.000+

Query logs

[07:46:06]- 2.6 ms – get_from_db - Reinforcement - Reinforcements.py(31)[07:46:06]- 4.3 ms - get_from_db - Player - Player.py(876)[07:46:10]- 0.1 ms - filter - Membership- AllianceMembership.py(110) [07:46:10]- 1.3 ms - get_from_db - Reinforcement -Reinforcements.py(31)[07:46:10]- 1.4 ms - get_from_db - Notifications - Notifications.py (56)

Page 41: Utopia Kingdoms scaling case. From 4 users to 50.000+

Scalability vs Efciency

Page 42: Utopia Kingdoms scaling case. From 4 users to 50.000+

Scalable vs Efcient

Scalable● Can support more

users adding more elements

Efficient● Can support more

users with the same elements

Work on both to achieve your goals

Page 43: Utopia Kingdoms scaling case. From 4 users to 50.000+

Keep measuring and improving!(and monitor production to be proactive)

Page 44: Utopia Kingdoms scaling case. From 4 users to 50.000+

Thank you for your interest!

Questions?

[email protected]://WrongSideOfMemphis.wordpress.com

http://www.joltonline.com


Top Related