在网上看了很多教程,可能每个人遇到的情况,都不一样,
重要的一点,很少有人提供了代码属性图(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,看到消息很及时