27
DJANGO CHANNELS by Chew Kok Hoor [email protected].

PyConMY 2016 Django Channels

Embed Size (px)

Citation preview

Page 1: PyConMY 2016 Django Channels

DJANGO CHANNELS

by Chew Kok Hoor [email protected]

Page 2: PyConMY 2016 Django Channels

About Me Also Director of Third Life Sdn. Bhd. – co-developer

of Mobile Marketing app for Businesses: channels.io

Web Applications - Django

Mobile Apps backend - Django

Point-of-Sales system (POS) - Django

POS Device Connectors - Tornado.

Page 3: PyConMY 2016 Django Channels

Objective

General overview of Channels

Simple Example

Scaling

Page 4: PyConMY 2016 Django Channels

What is Django Channels

“Channels is a project to make Django able to handle more than just plain HTTP requests, including WebSockets and HTTP2, as well as the ability to run code after a response has been sent for things like thumbnailing or background calculation.”- http://channels.readthedocs.io/

Page 5: PyConMY 2016 Django Channels

Web Applications Activities / Tasks

Respond to request (GET, POST, …)

Batch activities – slower tasks such as sending email etc.

Web Sockets

Page 6: PyConMY 2016 Django Channels

Python Frameworks / Libraries

Respond to request (GET, POST, …) DJANGO

Batch processing Celery, RQ, Gearman

Web Sockets Flask, Tornado, Twisted

Page 7: PyConMY 2016 Django Channels

Vanilla Django Built around

Requests and Responses

Incompatible with WebSockets.

Source: https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

Page 8: PyConMY 2016 Django Channels

Django Channels Addition of Async Interface

Server and Channels Layer (Asynchronous Server Gateway Interface)

Worker Processes able to handle Request / Response, WebSocket and Background Processes

Existing concepts of views still applies to Request & Response

Source: https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

Page 9: PyConMY 2016 Django Channels

Side-by-Side

Vanilla Django Django Channels

Daphne

In-Memory / IPC / Redis

Page 10: PyConMY 2016 Django Channels

Why Django Channels? Pros

Consolidate and centralize configuration and program code Easier re-use Asynchronous in nature but you still write synchronous

code – no yields, monkey-patching etc. In one big package, so improvements and directions can

be aligned.

Cons Celery more complete compared to what Channels has to

offer Channels Layer choices still limited (IPC, Redis) Stuck in an Opinionated Framework

Page 11: PyConMY 2016 Django Channels

Example app for Django Channels Borrowed code from

https://github.com/jacobian/channels-example/

Covers: Traditional Request Response

(TemplateViews) Batch (fake email sending) WebSockets

Page 12: PyConMY 2016 Django Channels

Getting Started

pip install channels pip install asgi_redis

settings.py

CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { "hosts": [‘redis://localhost:6379’], }, "ROUTING": "main.routing.default_routing", }}

Page 13: PyConMY 2016 Django Channels

Routingrouting.py

from channels.routing import routefrom . import consumersfrom . import batch

channel_routing = [ route('send-invite', batch.send_invite),]

chat_routing = [ route('websocket.connect', consumers.ws_connect), route('websocket.receive', consumers.ws_receive), route('websocket.disconnect', consumers.ws_disconnect),]

default_routing = channel_routing + chat_routing

Page 14: PyConMY 2016 Django Channels

asgi.pyimport osimport channels.asgi

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "channels_test.settings")

channel_layer = channels.asgi.get_channel_layer()

Page 15: PyConMY 2016 Django Channels

Excerpt of views.py class InviteView(TemplateView): template_name = "invite.html"

def post(self, request, *args, **kwargs): context = self.get_context_data() REQUEST_DATA = request.POST email = REQUEST_DATA.get('email') if not email: context['error'] = "Email field not provided" return super(TemplateView, self).render_to_response(context)

data = { 'email': email, 'message': u"Hi, %s, you're invited!! Check us out at http://www.solutionx.com.my for more info!" % email } Channel('send-invite', alias=settings.BATCH_CHANNEL_LAYER).send(data) context['message'] = "We're sending the invite for you!" return super(TemplateView, self).render_to_response(context)

Page 16: PyConMY 2016 Django Channels

batch.py

import loggingimport time

logger = logging.getLogger('email')

def send_invite(message): logger.info("We receive a request to send email to: " + message.get('email')) logger.info("Message: " + message.get('message')) time.sleep(10) logger.info("Email sent successfully!")

Page 17: PyConMY 2016 Django Channels

Running the processes1. redis-server

2. daphne main.asgi:channel_layer

3. python manage.py runworker

Page 18: PyConMY 2016 Django Channels

Scaling

1. Add more workers

2. Redis sharding (seems to still require further testing)

3. Multiple Channel Layers

Page 19: PyConMY 2016 Django Channels

Scaling1. Add more workers

- python manage.py runworker

Page 20: PyConMY 2016 Django Channels

Scaling (2)1. Redis sharding (still requires further

testing)

Page 21: PyConMY 2016 Django Channels

Redis Sharding

CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { "hosts": ['redis://localhost:6379', 'redis://localhost:7777'], }, "ROUTING": "main.routing.default_routing", }}

Page 22: PyConMY 2016 Django Channels

Running the processes (Sharding)

1. redis-server2. redis-server --port 7777

3. daphne main.asgi_sharding:channel_layer

4. python manage.py runworker --settings channels_test.settings_sharding

5. python manage.py runworker --settings channels_test.settings_sharding

Page 23: PyConMY 2016 Django Channels

Scaling (3)1. Multiple Channel Layers

Page 24: PyConMY 2016 Django Channels

Multiple Channel LayersCHANNEL_LAYERS = { "test": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { "hosts": [‘redis://localhost:6379’], }, "ROUTING": "main.routing.channel_routing", }, "chat": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { "hosts": [`redis://localhost:7777’], }, "ROUTING": "main.routing.chat_routing", },}

Page 25: PyConMY 2016 Django Channels

Running the processes (Multiple Channel Layers)1. redis-server2. redis-server --port 7777

3. daphne -b 0.0.0.0 -p 8000 main.asgi_test:channel_layer4. python manage.py runworker --settings

channels_test.settings_prod --layer test --only-channels http.request

5. python manage.py runworker --settings channels_test.settings_prod --layer test --only-channels send-invite

6. daphne -b 0.0.0.0 -p 8080 main.asgi_chat:channel_layer7. python manage.py runworker --settings

channels_test.settings_prod --layer chat

Page 27: PyConMY 2016 Django Channels

Q&A

Chew Kok HoorDirector

[email protected]

channels.io App (not related to Django Channels, name similarity purely co-incidental)

http://channels.io

Android