最近使用django框架做了一个简单的聊天机器人demo, 开发的过程中使用了django自带的websocket模块,当使用django框架自带的wsgi服务去启动的话,没有什么问题。如果要使用uwsgi启动的话,会报错:handshake的返回400,也就是客户端不合法。针对这边些问题,我去查询了官方文档,发现了我问题:

  1. django-websocket 是旧版本的,现在已经没有人维护了。dwebsocket是新版的,推荐使用dwebsocket;

  2.使用uwsgi启动的话,需要原有uwsgi.ini 配置信息下添加两行配置信息 

    2.1 websocket要使用uwsgi自带的websocket模块  

    2.2 # 加载项目配置
      DJANGO_SETTINGS_MODULE=py_webserver.settings
      WEBSOCKET_FACTORY_CLASS=”dwebsocket.backends.uwsgi.factory.uWsgiWebSocketFactory”

    2.3  启动脚本如下:uwsgi –ini ./conf/uwsgi.ini –http-websockets

  3.在nginx.conf配置文件中添加几行配置文件即可解决问题

 整个demo以及配置信息如下:

 1.项目结构:

   

2.pywebserever项目代码:

 conf 模块下的代码:

  mysql.ini

[mysqlsettings]
dbname = webSocket_chatbot
host = 127.0.0.1
port = 3306
uname = root
passwd = mysql

  pyweb_log.ini

[logs]
mail_level = ERROR
tofile_level = DEBUG
loggers_level = INFO

  uwsgi.ini (uwsgi启动项目的时候需要的配置文件)

[uwsgi]
#使用nginx连接时使用
socket=127.0.0.1:8080

#直接做web服务器使用
#http=127.0.0.1:8080

# 启动主进程
master=True
pidfile=uwsgi.pid

processes=4
threads=2

#项目目录
chdir=/home/python/Desktop/test_code/py_webserver

#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=py_webserver/wsgi.py

# 设置日志目录
daemonize=logs/uwsgi.log

# 设置缓存
buffer-size=32768

# 当服务器退出的时候自动删除unix socket 文件和pid 文件
vacuum = true

# 加载项目配置(django + websocket时需要配置的信息)
DJANGO_SETTINGS_MODULE=py_webserver.settings
WEBSOCKET_FACTORY_CLASS=”dwebsocket.backends.uwsgi.factory.uWsgiWebSocketFactory”

 pywebserver模块下的代码:

  urls.py: 

  1. from django.urls import path, include
  2. from django.contrib import admin
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. path('', include('webwork.urls')),
  6. ]

  settings.py:

  1. import os
  2. import configparser
  3. # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
  4. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  5. conf = configparser.ConfigParser()
  6. # Application definition
  7. INSTALLED_APPS = [
  8. 'django.contrib.admin',
  9. 'django.contrib.auth',
  10. 'django.contrib.contenttypes',
  11. 'django.contrib.sessions',
  12. 'django.contrib.messages',
  13. 'django.contrib.staticfiles',
  14. 'webwork', # 此处注册应用
  15. ]
  16. # Database
  17. # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
  18. conf.read(BASE_DIR + "/conf/mysql.ini")
  19. DATABASES = {
  20. 'default': {
  21. 'ENGINE': 'django.db.backends.mysql',
  22. 'NAME': conf.get("mysqlsettings", "dbname"),
  23. "Host":conf.get("mysqlsettings", "host"),
  24. "PORT":conf.get("mysqlsettings", "port"),
  25. "USER":conf.get("mysqlsettings", "uname"),
  26. "PASSWORD":conf.get("mysqlsettings", "passwd"),
  27. "CONN_MAX_AGE":600 # 增加连接池,保持数据 长连接600秒
  28. }
  29. }
  30. # Logs配置
  31. conf.read(BASE_DIR + "/conf/pyweb_log.ini")
  32. LOGGING = {
  33. 'version': 1,
  34. 'disable_existing_loggers': False,
  35. 'formatters': {
  36. 'standard': {
  37. 'format': '[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s',
  38. 'datefmt': '%Y-%m-%d %H:%M:%S'
  39. },
  40. },
  41. 'filters': {
  42. },
  43. 'handlers': {
  44. 'mail_admins': {
  45. 'level': conf.get("logs", "mail_level"),
  46. 'class': 'django.utils.log.AdminEmailHandler',
  47. 'formatter': 'standard',
  48. },
  49. 'tofile': {
  50. 'level': conf.get("logs", "tofile_level"),
  51. 'class': 'logging.FileHandler',
  52. 'formatter': 'standard',
  53. 'filename': os.path.join(BASE_DIR, 'logs/py_web.log'),
  54. },
  55. },
  56. 'loggers': {
  57. 'django': {
  58. 'handlers': ['tofile'],
  59. 'level': conf.get("logs", "loggers_level"),
  60. 'propagate': True,
  61. },
  62. }
  63. }

   __inint__.py

  1. import pymysql
  2. pymysql.install_as_MySQLdb()

 

 template模块下的代码:

  chat.html  

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Test Django Channels</title>
  6. </head>
  7. <body>
  8. <div style="text-align: center;margin-top: 50px">
  9. <input id="message" type="text" style="width: 300px" placeholder="输入消息">
  10. <button id="send-message" style="width:80px;margin-left:20px;">发送</button>
  11. <button id="close-message" style="width:80px;margin-left:20px;">关闭</button>
  12. <button id="connect-message" style="...">登录连接</button>
  13. <button id="test" style="...">测试长连接</button>
  14. </div>
  15. <table id="show-message" style="width: 410px;margin: 0 auto;margin-top: 10px">
  16. <tr>
  17. <td style="text-align: center; border-bottom:1px dashed #000;"><strong>聊天记录</strong></td>
  18. </tr>
  19. </table>
  20. </body>
  21. <script src="/static/js/jquery-3.2.1.min.js"></script>
  22. <script>
  23. var socket = new WebSocket('ws://' + window.location.host + '/users/');
  24. socket.onmessage = function (message) {
  25. updateLog("机器人", message.data);
  26. $("#message").val("");
  27. $("#message").focus();
  28. };
  29. socket.onopen = function () {
  30. };
  31. $("#connect-message").click(function () {
  32. socket = new WebSocket('ws://' + window.location.host + '/users/');
  33. socket.onmessage = function (message) {
  34. updateLog("机器人", message);
  35. $("#message").val("");
  36. $("#message").focus();
  37. };
  38. socket.onopen = function () {
  39. };
  40. });
  41. $("#close-message").click(function () {
  42. updateLog("机器人", "你好,此次服务结束");
  43. socket.close()
  44. });
  45. $("#send-message").click(function () {
  46. var inputText = $("#message").val();
  47. if (typeof(inputText) == "undefined" || inputText.length < 1) {
  48. alert("没有输入信息");
  49. }
  50. else {
  51. var msg = {"text": inputText};
  52. socket.send(JSON.stringify(msg));
  53. updateLog("", inputText);
  54. }
  55. });
  56. function updateLog(name, message) {
  57. var chat = $("#show-message");
  58. var ele = "<tr><td>" + name + ": " + message + "</td></tr>";
  59. chat.append(ele);
  60. }
  61. $("#test").click(function () {
  62. alert(socket.readyState);
  63. })
  64. </script>
  65. </html>

  webwork模块下的代码:

  models.py

  1. 1 from django.db import models
  2. 2
  3. 3 # Create your models here.
  4. 4
  5. 5 class MysqlModel(models.Model):
  6. 6 info = models.CharField(max_length=100)
  7. 7 save_time = models.DateTimeField()
  8. 8
  9. 9 class Meta:
  10. 10 db_table = "t_chatbot_test"

  urls.py

 

  1. 1 from django.urls import include, path
  2. 2 from webwork.views import ChatView, user
  3. 3
  4. 4 urlpatterns = [
  5. 5 path('', ChatView.as_view(), name='chat'),
  6. 6 path("users/", user, name="users")
  7. 7
  8. 8 ]

 

  view.py

 

  1. 1 from django.shortcuts import render
  2. 2 from django.views.generic.base import View
  3. 3 from .models import MysqlModel
  4. 4 import time
  5. 5 import uwsgi
  6. 6 import json
  7. 7 import logging
  8. 8
  9. 9
  10. 10 logger = logging.getLogger("django")
  11. 11 # Create your views here.
  12. 12
  13. 13 class ChatView(View):
  14. 14 """加载前端页面"""
  15. 15 @staticmethod
  16. 16 def get(request):
  17. 17 return render(request, "webwork/chat.html")
  18. 18
  19. 19
  20. 20 def user(request):
  21. 21 """接受websocket传递过来的信息"""
  22. 22 uwsgi.websocket_handshake()
  23. 23 uwsgi.websocket_send("你还,很高心为你服务")
  24. 24 while True:
  25. 25 msg = uwsgi.websocket_recv()
  26. 26 msg = msg.decode()
  27. 27 data = json.loads(msg)
  28. 28 data_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
  29. 29 talk_words = MysqlModel()
  30. 30 talk_words.info = data["text"]
  31. 31 talk_words.save_time = data_time
  32. 32 try:
  33. 33 talk_words.save()
  34. 34 talks = MysqlModel.objects.all()
  35. 35 except Exception as ret:
  36. 36 logger.info("save_data:" + str(ret))
  37. 37 else:
  38. 38 for talk in talks:
  39. 39 logger.info("talk_info:" + talk.info)
  40. 40 uwsgi.websocket_send(data["text"])

requirements.txt 中的依赖包

  1. gi-redis==1.0.0
  2. asgiref==1.0.0
  3. attrs==16.3.0
  4. autobahn==0.17.1
  5. Automat==0.5.0
  6. channels==1.0.3
  7. constantly==15.1.0
  8. daphne==1.0.3
  9. Django==2.0.3
  10. incremental==16.10.1
  11. msgpack-python==0.4.8
  12. PyMySQL==0.8.0
  13. pytz==2018.3
  14. redis==2.10.5
  15. six==1.10.0
  16. Twisted==17.1.0
  17. txaio==2.6.1
  18. txredisapi==1.4.4
  19. uWSGI==2.0.17
  20. zope.interface==4.3.3

3.uwsgi的配置:

  1. 3.1 安装uwsgi pip install uwsgi
  2. 3.2 在项目下的con文件下创建uwsgi.ini文件,具体配置信息如上边的uwsgi.ini文件所示
  3. 3.3 启动uwsgiuwsgi --ini ./conf/uwsgi.ini --http-websockets
  4. 3.4 查看uwsgi启动状态:ps -ef|grep uwsgi
  5. 3.5 启动之后在浏览器输入:127.0.0.1;8080 查看uwsgi服务器的状态
  6. 3.6 停止启动状态 uwsgi -- stop uwsgi.pid
4.nginx的配置:
  1. # 安装nginx并验证是否安装正确
    4.1 下载nginx后放到桌面上,解压缩 tar zxvf nginx-1.6.3.tar.gz4.2 进入nginx-1.6.3目录,依次执行以下命令进行安装
  2. ./configure (--prefix=<path>nginx 指定安装根目录)
  3. make
  4. sudo make install
  5. 4.3 默认安装到/usr/local/nginx/目录,进入此目录
  6. 4.4 启动: sudo sbin/nginx4.5.查看进程 ps -ef|grep nginx4.6 浏览器检测ngnix是否启动:http://127.0.0.1/
  7.  
  8. 4.7 关闭ngnix服务器:sudo sbin/nginx -s stop

    # nginx指向uwsgi
 4.8.主要配置节点:对于处理http协议的请求,主要配置三个节点
  • http:表示所有的http请求的处理
  • server:监听端口,绑定服务器
  • location:匹配请求路径,转到相应的处理
  1.   server {
         listen 80
         server_name localhost;

     
  2. location / {
  3. #将所有的参数转到uwsgi下
  4. include uwsgi_params;;
  5. #uwsgi的ip与端口
  6. uwsgi_pass 127.0.0.1:8080;
  7.  # websocket的匹配
  8. proxy_redirect off;
  9. proxy_http_version 1.1;
  10. proxy_set_header Upgrade $http_upgrade;
  11. proxy_set_header Connection "upgrade";
  12. }

        # 注释掉nginx server下的这几行配置

      #location / {
        # root html;
        # index index.html index.htm;
        # }

  1.  
  
 4.9.所有的静态文件都会由nginx处理,不会将请求转到uwsgi
    4.9.1.先生成静态文件目录   此项目我创建静态文件路径:/home/python/Desktop/test_code/django_static/websocket_static
    4.9.2.django的settings增加静态文件配置   

    STATIC_ROOT=”/home/python/Desktop/test_code/django_static/websocket_static”
     STATIC_URL = ‘/static/’

     # 将STATICFILES_DIRS的参数注释掉

   4.9.3 收集静态文件到 STATIC_ROOT 中

 4.10 在nginx.conf 的server下增加静态文件配置  

    location /static {
    alias /home/python/Desktop/test_code/django_static/websocket_static;
}

  1.  

 

  

 

 

 

   

 

    

 

版权声明:本文为lph-shares原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/lph-shares/p/8708786.html