Web Protocol


HTTPは基本的にリアルタイムでは不可能です.クライアントがサーバにリクエストを送信すると、リクエストの処理後に応答し、リクエストが切断されるためです.サーバはクライアントに通知できません.これは、サーバが非常に受動的であることを意味します(...)存在になる.

HTTP特性を補完する通信方式


Push Server


クライアントを介してリクエストを送信するのではなく、サーバを介してクライアントに通知します.

Polling


クライアントは、Webサーバに新しいコンテンツがあるかどうかを尋ね続けます.
  • Long Poling:サーバに新しいコンテンツがあるかどうかを尋ね、サーバは新しいコンテンツがある場合にのみ回答します.
  • Stream


    サーバ応答ヘッダにcontent-lengthが存在するかどうかに応じて、接続を維持します.Content-lengthが存在しない場合、クライアントは接続が切断されるまで応答を受け入れます.

    Web Socket


    リアルタイム双方向通信の仕様.HTML 5のサポートでプロトコル化されています.サーバとブラウザは、接続されたTCP回線を介してリアルタイムで通信する.

    Django Channel



    チャネルをインストールすると、ブラウザと通信するWebサーバとしてDaphneが自動的にインストールされます.HTTP通信のみを管理するNginxのようなサーバとして設計してもよい.

    Channels内部でRedisをスロット間に格納して通信(?)サーバとして使用します.
    # app/settings.py
    CHANNEL_LAYERS = {
        'default': {
            'BACKEND': 'channels_redis.core.RedisChannelLayer',
            'CONFIG': {
                "hosts": [('127.0.0.1', 6379)],
            },
        },
    }

    ASGI


    wsgiの欠点awaitは,asyncを可能な通信方式にする.django−channelsは基本的にこのような通信方式の上で実現される.

    ProtocolTypeRouter


    httpリクエストはアプリケーションで処理する役割ドメインを指定し、websocketは別の役割ドメインを指定します. appが異なるscopeを処理できるようにする.Httpを定義しない場合は、デフォルトのdjangoで操作します.
    application = ProtocolTypeRouter({
        # (http->django views is added by default)
    		'http' : basis_app,
        'websocket': AuthMiddlewareStack(
            URLRouter(
                chat.routing.websocket_urlpatterns
            )
        ),
    })

    Why need asynchronous?


    チャットを例にとると、チャットプレイヤーは私たちの期待に関係のない時間帯にチャットすることができます.毎回応答を要求および受信することができないため、受信ボックスの役割を果たすchannel layerを使用してすべての応答を受信し、通信方式をとることができる.
    Channelsは、非同期スレッドをdjangoに同期したCallableに変換するAPIをサポートします.
    # chat/consumers.py
    class ChatConsumer(WebsocketConsumer):
    	def receive(self, text_data):
    	    text_data_json = json.loads(text_data)
    	    message = text_data_json['message']
    
    	    # room group 에게 메세지 send
    	    async_to_sync(self.channel_layer.group_send)(
    	        self.room_group_name,
    	        {
    	            'type': 'chat_message',
    	            'message': message
    	        }
    	    )
    しかし、上記のコードはasync直接符号化時よりも効率的ではなく、以下のように変更することができる.
    # chat/consumers.py
    class ChatConsumer(AsyncWebsocketConsumer):
    	async def receive(self, text_data):
    	    text_data_json = json.loads(text_data)
    	    message = text_data_json['message']
    	
    	    # Send message to room group
    	    await self.channel_layer.group_send(
    	        self.room_group_name,
    	        {
    	            'type': 'chat_message',
    	            'message': message
    	        }
    	    )
    チャットルームを非常に良く実施する例:https://github.com/andrewgodwin/channels-examples/tree/master/multichat

    Background Worker


    クライアントとの通信とは異なり、社内スタッフもチャネルを介してメッセージを伝えることができます.すなわち、workerとserverの間のチャネルを貫通し、clientは単独で参照しません.
    注意:https://channels.readthedocs.io/en/latest/topics/worker.html
    コアは別の内部チャネルを設け、それぞれ「channel」のscopeを受信する.
    # app/routing.py
    
    application = ProtocolTypeRouter({
        # (http->django views is added by default)
        'websocket': TokenAuthMiddlewareStack(
            URLRouter(
                channelapp.routing.websocket_urlpatterns
            )
        ),
        'channel': ChannelNameRouter({
            'background-tasks': BackgroundTaskConsumer,
        })
    })
    そうすると、background-tasksという名前のworkerが別のチャンネルに入り、workerを開くときにこの名前を指定しなければなりません.そうすれば、正しいルーティング(?)
    python manage.py runworker background-tasks
    ワークを呼び出すときにも使用できます:https://github.com/jayhale/channels-examples-bg-task