所以,这就是问题:我有一个django网站,已经由apache服务多年,并使用LDAP用户身份验证(此事超出了我的控制范围和薪资等级)。我安装了Django Channels、asgi_redis、redis-server和与Django Channels自动关联的接口服务器Daphne。我还在CentOS 6/7上工作。
到目前为止,我已经弄清楚需要使用apache作为反向代理来与ASGI/Daphne进行通信,但我就是找不到需要的信息或自己弄清楚,显然如此。
以下是我能够找到的最接近的配置。我将我的apache配置文件设置为(URL是外部的,因为我的开发服务器是远程的;敏感信息当然已编辑):
< VirtualHost *:80 >
# Django Channels
ProxyPass "/ws/" "ws://192.168.xx.xx/"
ProxyPassReverse "/ws/" "ws://192.168.xx.xx/"
ProxyPass "/" "http://192.168.xx.xx/"
ProxyPassReverse "/" "http://192.168.xx.xx/"
WSGIDaemonProcess dashboard_jnett python-path=/home/jnett/dashboard_jnett:/home/jnett/airview_env/lib/python2.7/site-packages
WSGIScriptAlias /dashboard_jnett /home/jnett/dashboard_jnett/apache/dashboard_jnett.wsgi process-group=dashboard_jnett
<Directory /home/jnett/dashboard_jnett>
AuthType Basic
AuthName "Web Utilities"
AuthBasicProvider ldap
AuthGroupFile /dev/null
require valid-user
AuthLDAPBindDN "uid=authenticate,ou=system,dc=intranet,dc=row44,dc=com"
AuthLDAPBindPassword "xxxxxxx"
AuthLDAPURL ldap://192.168.xx.xx/ou=users,dc=intranet,dc=row44,dc=com?cn??(&(objectclass=inetOrgPerson)(member=cn=status))
Require ldap-filter objectClass=inetOrgPerson
</Directory>
Alias /static/dashboard_jnett /var/www/html/static/dashboard_jnett
<Directory /var/www/html/static/dashboard_jnett>
AllowOverride None
Require all granted
Options FollowSymLinks
</Directory>
</VirtualHost>
我通过浏览器访问网站根目录的方式是:http://192.168.xx.xx/dashboard_jnett/
在我的项目代码中,我有一个名为asgi.py
的文件:
import os
import channels.asgi
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings_jnett")
channel_layer = channels.asgi.get_channel_layer()
在ASGI文件中引用的设置文件settings_jnett.py
中,我有以下内容:
import asgi_redis
...
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://192.168.xx.xx:6379')],
"prefix": u"dashboard_jnett",
},
"ROUTING": "routing.channel_routing",
},
}
除此之外,还需要添加到INSTALLED_APPS
中的适当包,这一点我没有提到。
这确实指向了routing.py
文件,其中包含:
from channels.routing import route
from channeltest.consumers import ws_connect, ws_message, ws_disconnect, http_consumer
channel_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_message),
route("websocket.disconnect", ws_disconnect),
route("http.request", consumers.http_consumer),
#route("websocket.receive", "consumers.ws_message"),
]
这个文件会从 consumers.py
文件中导入。
from django.http import HttpResponse
from channels.handler import AsgiHandler
from channels import Group
from channels.sessions import channel_session
# Connected to websocket.connect
@channel_session
def ws_connect(message):
# Accept connection
message.reply_channel.send({"accept": True})
# Work out room name from path (ignore slashes)
room = message.content['path'].strip("/")
# Save room in session and add us to the group
message.channel_session['room'] = room
Group("chat-%s" % room).add(message.reply_channel)
# Connected to websocket.receive
@channel_session
def ws_message(message):
Group("chat-%s" % message.channel_session['room']).send({
"text": message['text'],
})
# Connected to websocket.disconnect
@channel_session
def ws_disconnect(message):
Group("chat-%s" % message.channel_session['room']).discard(message.reply_channel)
def http_consumer(message):
response = HttpResponse("Hello world! You asked for %s" % message.content['path'])
for chunk in AsgiHandler.encode_response(response):
message.reply_channel.send(chunk)
我在终端中使用以下命令运行了Daphne:
[jnett@dev03.nlv ~/dashboard_jnett ]$(airview_env)[jnett@dev03.nlv ~/dashboard_jnett ]$daphne -b 192.168.xx.xx asgi:channel_layer --port 6379
2017-08-23 18:57:56,147 INFO Starting server at tcp:port=6379:interface=192.168.xx.xx, channel layer asgi:channel_layer.
2017-08-23 18:57:56,147 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2017-08-23 18:57:56,147 INFO Using busy-loop synchronous mode on channel layer
2017-08-23 18:57:56,148 INFO Listening on endpoint tcp:port=6379:interface=192.168.xx.xx
2017-08-23 18:57:56,148 INFO HTTPFactory starting on 6379
2017-08-23 18:57:56,148 INFO Starting factory <daphne.http_protocol.HTTPFactory instance at 0x54aca28>
我在另一个终端上运行了一个工作程序,命令如下:
[jnett@dev03.nlv ~/dashboard_jnett ]$python manage.py runworker
2017-06-14 20:46:47,988 - INFO - runworker - Using single-threaded worker.
2017-06-14 20:46:47,988 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-06-14 20:46:47,989 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
我在另一个终端上运行了Redis服务器,命令如下:
[jnett@dev03.nlv ~/dashboard_jnett ]$~jnett/redis-stable/src/redis-server
...
10940:M 14 Jun 20:41:25.224 * The server is now ready to accept connections on port 6379
我现在甚至没有尝试使用WebSocket-我只是试图先处理正常的HTTP流量,但是我只能从apache收到代理错误:
代理错误
代理服务器从上游服务器接收到无效的响应。代理服务器无法处理请求GET/dashboard_jnett/channeltest/。
原因:无法从远程服务器读取错误
其中apache错误日志给出了很多行,例如:
[Wed Jun 14 21:39:52.718388 2017] [proxy_http:error] [pid 13123] (70007)指定的超时时间已过期:[client 192.168.xx.xx:51814] AH01102:从远程服务器192.168.xx.xx:80读取状态行时发生错误 [Wed Jun 14 21:39:52.718426 2017] [proxy:error] [pid 13123] [client 192.168.xx.xx:51814] AH00898:从/dashboard_jnett/channeltest/远程服务器读取时发生错误
是否有人成功将此设置投入生产?如果我能弄清楚如何使apache正确地将流量引导到Daphne以进行正常的HTTP,则我可以从那里找到方法。