【Django】django+supervisor+gunicorn+nginx部署微信公众号


在网上看了很多教程,可能每个人遇到的情况,都不一样,
重要的一点,很少有人提供了代码属性图(tree)

在上周折腾着部署了一个flask项目后,今天想起来自己的微信公众号服务还没使用nginx部署好,趁着周六折腾了半天总算部署成功了.

公众号代码放在最后面了.
步骤如下:

  • 使用Python runserver ip:port运行成功
  • gunicorn,使用gunicorn运行django服务
  • supervisor,使用supervisor运行起gunicorn
  • 使用nginx监听supervisor运行的端口

第一步建立虚拟环境:

  • 安装虚拟环境包
sudo pip install virtualenv 	# 安装虚拟环境

sudo pip install virtualenvwrapper 	# 安装虚拟环境扩展包

这两个是必要的

  • 使用
find  / -name  .bashrc

查找到该文件

  • 添加
export WORKON_HOME=$HOME/.virtualenvs

source /usr/local/bin/virtualenvwrapper.sh
  • 使用source .bashrc使其生效
root@iZ2zefnh58jmcioefostjpZ:/home/python/Desktop# source /root/.bashrc
virtualenvwrapper.user_scripts creating /root/.virtualenvs/premkproject
......
virtualenvwrapper.user_scripts creating /root/.virtualenvs/get_env_details

建立Python2/3虚拟环境,进入/退出虚拟环境,删除虚拟环境

mkvirtualenv 虚拟环境名(这个是创建Python2的虚拟环境)
make virtual environment
mkvirtualenv 虚拟环境name
创建Python3虚拟环境:
mkvirtualenv -p python3 虚拟环境name
进入虚拟环境,workon 虚拟环境name
退出虚拟环境:deactivate
删除虚拟环境:rmvirtualenv 虚拟环境name

使用 manage.py runserver ip:port运行

这一步运行成功,并拿到想要的结果,我使用是,get请求,hello,world,来测试的…

使用gunicorn运行

在项目虚拟环境下:cd到django项目下:
执行:

gunicorn -w 4 -b ip:port project_name.wsgi:application

这个wsgi是固定的,application也是固定的,不用修改.

使用postman或者浏览器访问下,试试是否成功
不成功,使用

ps aux | grep gunicorn

或者
ps aux | grep PORT
看看是否运行成功

supervisor运行gunicorn.

Python3安装不了supervisor,解决办法可以参考
如何在Python3的项目里使用supervisor
简单点说,就是另外建立一个Python2的虚拟环境,在Python2的环境里,安装supervisor

我就把配置文件设置到了django项目里.

指定路径生成supervisor配置文件:

echo_supervisord_conf > etc/supervisord.conf

修改supervisor配置文件

command = /root/.virtualenvs/wechat/bin/gunicorn -w 4 -b IP:PORTWeChat.wsgi:application	; command
directory=/home/python/Desktop/wechat/WeChat/							; 项目的文件夹路径
autostart=true                                                                              	 ; 是否自动启动
autorestart=true                                                                               ; 是否自动重启
stdout_logfile=/home/python/Desktop/wechat/WeChat/logs/gunicorn.log                                     ; log 日志
stderr_logfile=/home/python/Desktop/wechat/WeChat/logs/gunicorn.err                                     ; 错误日志

使用指定路径的supervisor配置文件

supervisord -c /etc/supervisor/supervisord.conf

运行起来后

查看下gunicorn,端口是否都正常在运行
然后访问下测试用的url.如果成功,就可以去搞nginx服务了

nginx

nginx的配置,顺利的时候很顺利,不顺利的时候很不顺

查找一下nginx的路径

有些时候安装nginx的时候,可以使用

nginx -t

测试是否配置可用,顺带着也可以获取到配置conf文件的路径

要是不行,就可以使用

find / -name *nginx*

来获取结果

我的路径在这里,这个应该也是很常见的路径

/usr/local/nginx/conf

配置nginx配置文件

    server {
        listen 80;
        server_name IP;

        location / {
                proxy_pass http://0.0.0.0:8080;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    }
        }

就可以了

重启nginx服务

重启nginx服务前,可以使用

nginx -t

如果这个可用的话,测试下nginx配置信息
如果提示
-bash: nginx: command not found
则不可用

进入sbin可执行文件夹下

/usr/local/nginx/sbin

执行

./nginx -t

可以看到结果,这样是正常的

(py2_wechat) [root@host sbin]# ./nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

就可以重启了
还是在这个路径下:

./nginx -s reload

配置nginx遇到的bug

./nginx -t

报错信息

nginx: [emerg] unexpected "}" in /usr/local/nginx/conf/nginx.conf:109
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

这样就是少了一个},找个编辑器,好好看看括号…

重启的时候,nginx: [error] invalid PID number “” in “/usr/local/nginx/logs/nginx.pid”
(py2_wechat) [root@host sbin]# ./nginx -s reload
nginx: [error] invalid PID number "" in "/usr/local/nginx/logs/nginx.pid"

解决方案:
在目录

(py2_wechat) [root@host sbin]# pwd
/usr/local/nginx/sbin

下,执行

./nginx -c /usr/local/nginx/conf/nginx.conf

微信公众号代码

from django.shortcuts import render

# Create your views here.
from django.http.response import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt  # 解除csrf验证
from wechat_sdk import WechatConf
from wechat_sdk import WechatBasic
import logging
import json
import hashlib
import xmltodict
import time
import urllib
import xml.etree.ElementTree as ET
Token = 'luobo'

conf = WechatConf(  # 实例化配置信息对象
    token='***',  # 服务器配置-Token,替换自己的
    appid='****',  # 公众号开发信息-开发者ID,替换自己的
    appsecret='***',  # 公众号开发信息-开发者密码,替换自己的
    encrypt_mode='normal',  # 服务器配置-明文模式,替换自己的
    encoding_aes_key='****'  # 服务器配置-EncodingAESKey,替换自己的
)


@csrf_exempt  # 去除csrf验证
def wechat_token(request):
    logging.debug('--进了这个函数了--')
    signature = request.GET.get('signature')  # 获取请求信息
    logging.debug(signature)
    timestamp = request.GET.get('timestamp')
    logging.debug(timestamp)
    nonce = request.GET.get('nonce')
    logging.debug(nonce)
    logging.debug('request method info')
    logging.debug(request.method)
    wechat_instance = WechatBasic(conf=conf)  # 实例化微信基类对象
    if not wechat_instance.check_signature(signature=signature, timestamp=timestamp, nonce=nonce):  # 检查验证请求的签名
        # logging.debug('error???')
        return HttpResponseBadRequest('Verify Failed')
    else:
        # logging.debug('检查不合适???')
        if request.method == 'GET':
            # logging.debug('GET???')
            return HttpResponse(request.GET.get('echostr', None))  # 返回请求中的回复信息
        # logging.debug("难道因为不是post请求?")
    # logging.debug('为啥没走上面的判断')
    # post 请求
    if request.method=='POST':
        logging.debug('post进来了')
        try:
            logging.debug(request)
            xml = request.body
            req = xmltodict.parse(xml)['xml']
            logging.debug('--req--')
            logging.debug(req)
            msg_type = req['MsgType']
            # logging.debug('----msg_type--------')
            # logging.debug(msg_type)
            resp = {
                'ToUserName': req['FromUserName'],
                'FromUserName': req['ToUserName'],
                'CreateTime': int(time.time()),
            }
            if 'text' == msg_type:
                logging.debug('text')
                content = str(req['Content'])
                resp["MsgType"] = "text"
                resp['Content'] = content
                # logging.debug(resp)
                
            elif msg_type == 'image':
                resp["MsgType"] = "image"
                content = "图片已收到,谢谢"
            elif msg_type == 'voice':
                resp["MsgType"] = "voice"
                content = "语音已收到,谢谢"
            elif msg_type == 'video':
                resp["MsgType"] = "video"
                content = "视频已收到,谢谢"
            elif msg_type == 'shortvideo':
                resp["MsgType"] = "shortvideo"
                content = "小视频已收到,谢谢"
            elif msg_type == 'location':
                resp["MsgType"] = "location"
                content = "位置已收到,谢谢"
            else:
                msg_type = 'link'
                resp["MsgType"] = "link"
                content = "链接已收到,谢谢"
            resp['Content'] = content
            xml = xmltodict.unparse({'xml': resp})
            # logging.debug(xml)
            return HttpResponse(xml)

        except Exception as e:
            logging.debug(e)
            return HttpResponse(e)


def get_hello_world(request):
    if request.method == 'GET':
        print('hello world')
        return HttpResponse(json.dumps({"hello": "world"}))  # 返回请求中的回复信息

url

urlpatterns = [
       url(r'^wechat/token$',views.wechat_token),  # 测试token使用的
       url(r'^hello/world',views.get_hello_world)  # 测试hello world的
   ]

代码结构图

supervisord.conf可以放在这里,指定路径就好了
nginx.conf是为了方便修改.
就是一个很简单的公众号
代码结构图

关于建立这个公众号

更多的可能是为了练练手吧.写写代码,尝试更多的方法去部署,去学习,去使用

nginx这个是真的麻烦…如果配置不顺利的话,中途还删除过一次nginx,要疯…
使用

find / -name *nginx*

将查找到的文件,一个一个删除了…

如果有疑问,可以留言一起探讨下,总登陆CSDN,看到消息很及时

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值