Coder Social home page Coder Social logo

aaugustin / django-c10k-demo Goto Github PK

View Code? Open in Web Editor NEW
666.0 44.0 54.0 289 KB

10 000 concurrent real-time connections to Django [UNMAINTAINED]

License: BSD 3-Clause "New" or "Revised" License

Makefile 1.10% Python 85.86% JavaScript 5.70% HTML 6.81% CSS 0.52%

django-c10k-demo's Introduction

README

This experiment depends on internals of ``aiohttp`` which tend to change often and increase in complexity. It isn't maintained any longer.

django-c10k-demo is an experimental playground for high concurrency in Django with WebSockets.

It was originally written to handle 10 000 concurrent real-time connections to Django, hence the name.

It combines several interesting concepts: the C10k problem, the WebSocket protocol, the Django web framework, and Python's built-in asynchronous IO support.

Running the code

Prerequisites

  • Install Python 3.4 or 3.3.
  • Install aiohttp, Django, and websockets, most likely with virtualenv and pip. If you're using Python 3.3, install asyncio.
  • Clone this repository.
  • Configure your OS to allow lots of file descriptors. On OS X: sudo sysctl -w kern.maxfiles=40960 kern.maxfilesperproc=20480
  • Open two shells and bump their file descriptor limit: ulimit -n 10240

Game of Life demo

This demo is a distributed Game of Life. One client manages the life of one cell. Clients connect to a server through a WebSocket and register to receive updates from their neighbors. The server coordinates the startup sequence and relays messages between clients, but it doesn't know anything about the rules of the game; all the logic is handled by the clients!

  • In the first shell, start the server: python manage.py runserver
  • In the second shell, start the workers: python manage.py gameoflife
  • In a browser, go to http://localhost:8000/

gameoflife shouldn't display anything. runserver should display an increasing number of workers connected and then an increasing number of workers subscribed.

The page in the browser registers to receive updates from all clients, and updates in real time as soon as the workers start running. Alive cells are dark, dead cells are light. Their hue shifts slightly at each step to show how the grid updates.

image

gameoflife accepts a number of options to configure the game:

  • The size of the grid is 32. You can change it with -s.
  • The initial state is random with one cell alive out of four on average. You can load a pattern from a file with -p. See gameoflife/patterns/ for some common examples.
  • When a pattern is provided, it's centered on the grid. You can disable this behavior with -C.
  • The grid is cyclic: the left side is connected to the right side and the top to the bottom. You can disable this behavior with -W, for example to test guns.
  • The workers run forever, unless you specify a number of steps with -n.
  • The workers make at most one step per second — this only matters on small grids since the game won't run that fast on larger grids. You can adjust the speed limit with -l.

C10k demo

This is the original demo in this project. It handles 10 000 concurrent real-time connections to Django.

  • In the first shell, start the server: python manage.py runserver
  • In the second shell, start the clients: python manage.py testecho

runserver shouldn't display anything and testecho should show the number of connections, peaking at 10000 clients are connected!.

The connections are established over a period of two minutes. Once connected, each client repeats the following sequence three times: wait one minute, send a message, and read the reply of the server. Clients also receive a welcome and a goodbye message from the server. The entire demo takes five minutes if your system is fast enough.

If you don't reach 10 000 connections, it means that some clients finish their sequence and disconnect before all the clients are connected, because your system is too slow. If you see exceptions, it means that your OS isn't tuned correctly for such benchmarks. Decreasing CLIENTS or increasing DELAY in testecho may help in both cases.

Under the hood

Here are the underlying components in no particular order, with some hints on their quality and reusability.

WebSocket API for Django

Here's an example of a WebSocket echo server in Django:

from c10ktools.http import websocket

@websocket
def handler(ws):
    yield from ws.send((yield from ws.recv()))

WebSocket handlers are hooked in the URLconf like regular HTTP views. Arguments can be captured in the URLconf and passed to the handlers.

This doesn't allow sharing an URL between a regular HTTP view and a WebSocket handler, but I'm happy with this limitation as it's probably a good practice to keep them separate anyway.

Inside a WebSocket handler, you can use yield from ws.recv() and yield from ws.send() freely. You can also call yield from ws.send() outside the handler.

The @websocket decorator should only be applied to coroutines. It takes care of closing the WebSocket connection when the handler terminates.

Hook for the upgrade to WebSocket

The API described above requires the upgrade from HTTP to WebSocket to happen after Django's URL dispatcher has routed the request to a view. As a consequence, the upgrade must be performed within the framework of WSGI.

PEP 3333 predates real-time on the web and PEP 3156 doesn't propose to update it. This point might be addressed by a future version of the standard (PEP 3356 anyone?) In the meantime our only choice is to bastardize WSGI, steering away from compliance — sorry Graham.

The WebSocket opening handshake is completed by sending a HTTP response. This is achieved with WSGI, but it isn't compliant because the response includes hop-by-hop headers, Upgrade and Connection.

The switch to the WebSocket protocol is performed in close(). In asyncio terms, the transport is disconnected for the HTTP protocol and reconnected to the WebSocket protocol. Then a task is started to run the WebSocket handler and close the connection when it terminates. This design is very debatable:

  • This isn't an intended use case for the close() method.
  • The protocol transplant relies on non-standard variables in environ.
  • It abuses private APIs of asyncio and of aiohttp which aren't quite stable.

Asynchronous development server

django-c10k-demo takes advantage of aiohttp's WSGI support to adapt Django's built-in developement server to run on top of asyncio.

This component can be used independently by adding the 'c10ktools' application to INSTALLED_APPS. It monkey-patches the django-admin.py runserver command to run on top of the asyncio event loop.

Asynchronous production server

django-c10k-demo works with aiohttp's gunicorn worker class:

$ gunicorn -k aiohttp.worker.AsyncGunicornWorker c10kdemo.wsgi

Of course, this stack is experimental. It's unlikely to ever become "production-ready". Use it at your own risk!

django-c10k-demo's People

Contributors

aaugustin avatar ptone avatar xordoquy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-c10k-demo's Issues

gameoflife demo can't run. (under winxp. python3.4)

I download the c10k demo, and run it as below step.

  1. In the first shell, start the server: python manage.py runserver
  2. In the second shell, start the workers: python manage.py gameoflife
  3. In a browser, go to http://localhost:8000/
    when i visit http://localhost:8000/ . but, I see nothing on the http://localhost:8000/ . if i refresh the webpage, i can seen "Watcher connected" and "Watcher disconnected" printed in the webserver shell.
    when i visit "http://localhost:8000/watcher", "http://localhost:8000/reset" and "http://localhost:8000/worker", i met a InvalidHandshake error on every page.
    for example, when visit "http://localhost:8000/watcher", error message as below:
InvalidHandshake at /watcher/

Invalid request

Request Method:     GET
Request URL:    http://127.0.0.1:8000/watcher/
Django Version:     1.6.2
Exception Type:     InvalidHandshake
Exception Value:    

Invalid request

Exception Location:     C:\Python34\lib\site-packages\websockets\handshake.py in check_request, line 89
Python Executable:  C:\Python34\python.exe
Python Version:     3.4.0
Python Path:    

['D:\\test\\python\\django\\django-c10k-demo-master',
 'C:\\WINDOWS\\system32\\python34.zip',
 'C:\\Python34\\DLLs',
 'C:\\Python34\\lib',
 'C:\\Python34',
 'C:\\Python34\\lib\\site-packages']

Server time:    Sat, 5 Apr 2014 13:22:13 +0800
Traceback Switch to copy-and-paste view

    C:\Python34\lib\site-packages\django\core\handlers\base.py in get_response

                            response = wrapped_callback(request, *callback_args, **callback_kwargs)

        ...
    ▶ Local vars
    D:\test\python\django\django-c10k-demo-master\c10ktools\http\websockets.py in wrapper

                return WebSocketResponse(environ, switch_protocols)

        ...
    ▶ Local vars
    D:\test\python\django\django-c10k-demo-master\c10ktools\http\websockets.py in __init__

                key = handshake.check_request(get_header)

        ...
    ▶ Local vars
    C:\Python34\lib\site-packages\websockets\handshake.py in check_request

                raise InvalidHandshake("Invalid request") from exc

        ...
    ▶ Local vars 

a UnicodeEncodeError occurred when using c10ktools in non-english Django project.

I want use "@websockt" in my Django project, so I add the c10ktools app in my Django project.
but when i visit a webpage which contains non-english charsets. I met a error in server shell. as below:

D:\test\python\django\mysite>python manage.py runserver 192.168.1.100:80
Validating models...

0 errors found
April 12, 2014 - 14:15:30
Django version 1.6.2, using settings 'mysite.settings'
Starting development server at http://192.168.1.100:80/
Quit the server with CTRL-BREAK.
ERROR:root:Error handling request
Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\aiohttp\server.py", line 196, in start
    yield from handler
  File "C:\Python34\lib\site-packages\aiohttp\wsgi.py", line 161, in handle_requ
est
    riter = self.wsgi(environ, response.start_response)
  File "C:\Python34\lib\site-packages\django\contrib\staticfiles\handlers.py", l
ine 66, in __call__
    if not self._should_handle(get_path_info(environ)):
  File "C:\Python34\lib\site-packages\django\core\handlers\base.py", line 259, i
n get_path_info
    path_info = path_info.encode('iso-8859-1')
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 17-20: o
rdinal not in range(256)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.