Repository: django/channels

Issue:
Consumers should be able to listen on non-default channel layers
I have two channel layers defined in settings: "default" and "progress" (with short lifetime of messages)
```
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
    "progress": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
            "prefix": "progress",
            "expiry": 5,
        },
    },
}
```

The routing is:
```
application = ProtocolTypeRouter({
...
    "channel": ChannelNameRouter({
        'o-ready': Consumer,
        'o-progress': ProgressConsumer,
    })
})
```

I run two workers: one for "o-ready" channel and one for "o-progress". 
The issue is when the `ProgressConsumer` is instantiated and receiving a message the `self.channel_layer` points to "default" layer instead of "progress" layer. The reason of this the line 42 of channels/consumer.py:

[https://github.com/django/channels/blob/master/channels/consumer.py#L42](url)
```
# Initalize channel layer
self.channel_layer = get_channel_layer()   # <-- line 42
```
It seems the channel_layer should be initialized with the channel_layer from worker to use correct layer when send message from consumer via `self.send`.

Windows, Python 3.6.5, channels 2.1.1, channels-redis 2.1.1, django 2.0.5



Discussion:
Yeah, the `channel_layer` attribute is fixed to the default layer for now; multi-layer support is very thin in Channels 2. I'll turn this into a feature request ticket and leave it open for future implementation, though it likely has to be an attribute on the consumer, not a function of the worker.
Hi @andrewgodwin , I was wondering if there is any chance I can try to implement this feature?
@ZijianHe You're more than welcome to work on it! What sort of guidance do you need?
@andrewgodwin Thanks Andrew. I figure I have all information to get started as it a simple one and I think I will be able to make a pr for it within today
Hi @andrewgodwin 

Looks like this one is no longer being worked on? If this is the case can I have a go at it?
@ross-weir Feel free to have a crack - you'll want to look at the previous PR and my comments on it too I suspect.

Resolving patch:
diff --git a/channels/consumer.py b/channels/consumer.py
--- a/channels/consumer.py
+++ b/channels/consumer.py
@@ -2,6 +2,7 @@
 
 from asgiref.sync import async_to_sync
 
+from . import DEFAULT_CHANNEL_LAYER
 from .db import database_sync_to_async
 from .exceptions import StopConsumer
 from .layers import get_channel_layer
@@ -30,6 +31,7 @@ class AsyncConsumer:
     """
 
     _sync = False
+    channel_layer_alias = DEFAULT_CHANNEL_LAYER
 
     def __init__(self, scope):
         self.scope = scope
@@ -39,7 +41,7 @@ async def __call__(self, receive, send):
         Dispatches incoming messages to type-based handlers asynchronously.
         """
         # Initalize channel layer
-        self.channel_layer = get_channel_layer()
+        self.channel_layer = get_channel_layer(self.channel_layer_alias)
         if self.channel_layer is not None:
             self.channel_name = await self.channel_layer.new_channel()
             self.channel_receive = functools.partial(


Test patch:
diff --git a/tests/test_generic_websocket.py b/tests/test_generic_websocket.py
--- a/tests/test_generic_websocket.py
+++ b/tests/test_generic_websocket.py
@@ -196,6 +196,41 @@ async def receive(self, text_data=None, bytes_data=None):
         assert channel_layer.groups == {}
 
 
+@pytest.mark.asyncio
+async def test_async_websocket_consumer_specific_channel_layer():
+    """
+    Tests that AsyncWebsocketConsumer uses the specified channel layer.
+    """
+    results = {}
+
+    class TestConsumer(AsyncWebsocketConsumer):
+        channel_layer_alias = "testlayer"
+
+        async def receive(self, text_data=None, bytes_data=None):
+            results["received"] = (text_data, bytes_data)
+            await self.send(text_data=text_data, bytes_data=bytes_data)
+
+    channel_layers_setting = {
+        "testlayer": {"BACKEND": "channels.layers.InMemoryChannelLayer"}
+    }
+    with override_settings(CHANNEL_LAYERS=channel_layers_setting):
+        communicator = WebsocketCommunicator(TestConsumer, "/testws/")
+        await communicator.connect()
+
+        channel_layer = get_channel_layer("testlayer")
+        # Test that the specific channel layer is retreived
+        assert channel_layer != None
+
+        channel_name = list(channel_layer.channels.keys())[0]
+        message = {"type": "websocket.receive", "text": "hello"}
+        await channel_layer.send(channel_name, message)
+        response = await communicator.receive_from()
+        assert response == "hello"
+        assert results["received"] == ("hello", None)
+
+        await communicator.disconnect()
+
+
 @pytest.mark.asyncio
 async def test_json_websocket_consumer():
     """