Upload
kok-hoor-chew
View
194
Download
1
Embed Size (px)
Citation preview
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.
Objective
General overview of Channels
Simple Example
Scaling
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/
Web Applications Activities / Tasks
Respond to request (GET, POST, …)
Batch activities – slower tasks such as sending email etc.
Web Sockets
Python Frameworks / Libraries
Respond to request (GET, POST, …) DJANGO
Batch processing Celery, RQ, Gearman
Web Sockets Flask, Tornado, Twisted
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
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
Side-by-Side
Vanilla Django Django Channels
Daphne
In-Memory / IPC / Redis
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
Example app for Django Channels Borrowed code from
https://github.com/jacobian/channels-example/
Covers: Traditional Request Response
(TemplateViews) Batch (fake email sending) WebSockets
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", }}
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
asgi.pyimport osimport channels.asgi
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "channels_test.settings")
channel_layer = channels.asgi.get_channel_layer()
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)
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!")
Running the processes1. redis-server
2. daphne main.asgi:channel_layer
3. python manage.py runworker
Scaling
1. Add more workers
2. Redis sharding (seems to still require further testing)
3. Multiple Channel Layers
Scaling1. Add more workers
- python manage.py runworker
Scaling (2)1. Redis sharding (still requires further
testing)
Redis Sharding
CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { "hosts": ['redis://localhost:6379', 'redis://localhost:7777'], }, "ROUTING": "main.routing.default_routing", }}
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
Scaling (3)1. Multiple Channel Layers
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", },}
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
Wrapping Up New but promising Hopefully makes writing complex web apps
easier
References: https://blog.heroku.com/
in_deep_with_django_channels_the_future_of_real_time_apps_in_django
http://www.machinalis.com/blog/introduction-to-django-channels/
http://channels.readthedocs.io/en/latest/ https://github.com/andrewgodwin/channels
Q&A
Chew Kok HoorDirector
channels.io App (not related to Django Channels, name similarity purely co-incidental)
http://channels.io
Android