微信抢票作业——个人总结
#why should we put this on a blog?!
#please ignore it like what python will do for these 2 line
本次微信抢票公众平台开发, 对后端服务器有了一些接触, 也对Django有了更深的理解. 整个实验的收获还是比较大的, 一些遗憾的地方就是没能测服务器的并发量, 而且还没有对锁进行优化, 在锁中有过多的请求, 可能对性能有比较大的影响
本次实验个人任务完成大致可以分为以下三个阶段:
1、任务启动
任务启动阶段, 我对开发环境进行了解、配置, 并写了一个简单的教程供组员间分享(见下方),之后也帮助其他组员解决了一些搭建环境中碰到的问题. 以此, 我们对项目有了一个大致的了解, 并使组内各个模块的负责人都可以比较方便的在本地进行调试.
ngrok 真的是一个神器
#-------------------------------------------------------------------------#
1、pip(or pip3) install -r requirements.txt
- mysqlclient安装前先本地安装mysql
- 不要用最新版本的django: 不要分别pip install django和mysqlclient 或 pip install —upgrade django, admin界面只有原版本才能用, 新版本会报错: ‘WSGIRequest’ object has no attribute ‘user’ ,未解决 ,其余bug尚属未知
2、
把config.example.json 改为 configs.json
修改wechat/models.py, line40 为:
activity = models.ForeignKey(Activity,on_delete=models.DO_NOTHING)
a bug for windows:
修改DB相关的配置
"DB_NAME": "wtf",
"DB_USER": "root",
"DB_PASS": "YOUR_PASSWORD",
"DB_HOST": "localhost",
"DB_PORT": "3306",
让django链接到你的mysql数据库上, 如果没有就新建一个. 然后
$ python manage.py makemigrations
$ python manage.py migrate
这个不多说了,都懂
3、获取测试号: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login , 扫码登录后, 把得到的appID和appSecret填入configs.json
wx_token 需要自己生成3~32位随机串, 可以用python的os模块:
>>> import os
>>> import base64
>>> os.urandom(16).hex();
将wx_token填入configs.json
4、将服务器部署在80端口上
windows下应该可以直接runserver 80 解决, OS X需要其他一些设置, 参见: http://shaofan.org/mac-bind-80-port/
5、获取公网IP
分配给我们的服务器应该不用考虑这个问题. 如果想在自己电脑上试的话可以使用ngrok
注意将对外开放的域名放入settings.py的ALLOWED_HOSTS, 并修改configs.json文件的site_domain.
6、微信接入:
将 h t t p : / / y o u r a d d r e s s / w e c h a t http://youraddress/wechat http://youraddress/wechat填入URL中,token填你之前填入configs.json的wx_token 点击提交
(*我在这个地方碰到奇怪的事:连点按了几次提交它就从失败变成成功了……可能是宿舍网络波动了吧)
7、注册菜单:
接入微信后,可以根据开发者中心的提示获取access_token(见https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183)
获取token后, 向api.weixin.qq.com发送POST请求注册菜单(见https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013):
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
菜单对应的json在/wechat/views.py下,
event_keys = {
'book_what': 'SERVICE_BOOK_WHAT',
'get_ticket': 'SERVICE_GET_TICKET',
'account_bind': 'SERVICE_BIND',
'help': 'SERVICE_HELP',
'book_empty': 'BOOKING_EMPTY',
'book_header': 'BOOKING_ACTIVITY_',
}
menu = {
'button': [
{
"name": "服务",
"sub_button": [
{
"type": "click",
"name": "抢啥",
"key": event_keys['book_what'],
},
{
"type": "click",
"name": "查票",
"key": event_keys['get_ticket'],
},
{
"type": "click",
"name": "绑定",
"key": event_keys['account_bind'],
},
{
"type": "click",
"name": "帮助",
"key": event_keys['help'],
}
]
},
{
"name": "抢票",
"sub_button": []
}
]
}
注意手动把event_keys换掉来发送请求 然后把“抢票”那块直接删了算了……或者修改成别的也可以? 抢票那块不动的话微信api将返回invalid button type hint: [DZ0C308113129] 的error
8、今天新解决的bug:
User中student默认为unique.新用户登录时, 如果查找不到该微信号(openID)绑定的学号,会新建一个学号为空串的用户. 一旦有人接入而不绑定学号时, 其他用户再进入公众号, 数据库中无法新建一行用户数据, 将提示公众号提供服务出现故障.
为了不自己写学号查重, 暂时将默认学号改为openID,希望写绑定逻辑的同学注意将invalid的学号视为未绑定.(现在点击或回复“绑定”会直接把openID当做已绑定学号).
#-------------------------------------------------------------------------#
在这个阶段, ngrok这项神器对我们起到的帮助是最大的, 而且整个操作流程也十分的简单, 不另开贴说明, 附在下方:
登录 https://ngrok.com: 点击Get Started for free, 注册(可以使用Github账号授权登录)后将出现以下页面:
它会自动帮你识别你的系统, 提供相应的下载链接.
注意 第2步unzip 可能会由浏览器自动帮你解压完成, 在相应文件夹直接运行ngrok就好
第3步 connect your account: 双击ngrok后将进入terminal/cmd 会话, 在其中运行网页给出的命令
$ ./ngrok authtoken yourtoken
注意yourtoken位置会是一串token, 那个就是你自己独一无二的token(而非示例)
第4步 Enjoy your ngrok!
$ ngrok http 8000 #port you like
运行ngrok http port
命令后, 访问Forwarding给出的域名即可跳转到本地指定的端口了
- https
- 每一次重新启动ngrok都会产生一个新的域名
现在启动你的django(或者其他的)程序, 你应该可以在其他电脑/手机上访问到它了
$ python manage.py runserver port
2、开发阶段
一开始负责用户相关的接口的时候没有遇到什么障碍(当然也有后续模块调用时才暴露问题的原因), 在着手写新的handler时花了点工夫: 在项目文件夹中搜索user/bind 或 /api/u等, 厘清了原框架间接口的调用关系: 建立一个新的事件响应(如“查票”), 需要建立新的handler对象, 并在settings.py中将它引入. 之后则是花时间了解了Django models的锁相关接口(select_for_update() & atomic()), 实现了抢票的逻辑.
- 特别感谢队友把我的锅抢着做完了
3、部署阶段
使用Django+uWSGI+nginx 的组合 参考 https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html, 大致分为以下几步:
step 1: 安装相关组件后, 建立test.py
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"wtf"] # python3
#return ["wtf"] # python2
shell 测试
uwsgi --http :8000 --wsgi-file test.py
访问你的域名http:yourdomain:8000/ 如果显示wtf证明
client <—> uWSGI <—> Python 间通信顺畅
step 2: 验证client <—> uWSGI <—> Django 之间的通信是否通畅: 运行以下命令
$ sudo uwsgi --http :80 --module /path/to/your/project/project.wsgi
访问服务器域名, 正常打开管理员界面后证明连接顺畅
step 3: 验证nginx是否正常工作:
$ sudo /etc/init.d/nginx start
访问域名, 得到Welcome to NginX的页面时说明连接成功
step 4: 连接nginx与uwsgi以启动Django
编辑好uwsgi与nginx的配置文件, 分别开启nginx 与 uwsgi:
$ sudo nginx -c /etc/nginx/example.conf
$ sudo uwsgi --ini /path/to/your/uwsgi_ini/example.ini
step 5: 连接微信公众平台并验证通信顺畅
tips:
- 我自己一开始死活不成功的原因是分配的服务器8000端口防火墙不放通
- uwsgi path to your project 最好是绝对路径, 你可以在uwsgi运行后的log中看是否有Import Error来确认路径是否正确
- (引自xkcd) 如图
总结:
- ngrok真是太好用了
- 快速推进的时候, 可以祭出sudo(我知道这很不靠谱)