记一次非常痛苦的解决问题过程
零、背景
之前给微信公众号“爱手工”做过微信后台,最近由于服务器要更换,所以需要将后台迁移到新服务器上。
一、问题出现
本来以为很轻松就能搞定,安装Django以及各种依赖库,迁移数据,上传代码。
简短截说,这里很重要的一步就是我想当然的用mysqldump来迁移数据,这是第一处错误。
迁移过去以后,配置好nginx,runfcgi,用微信测试了一下发现无法正常工作。
kill掉Python进程,用runserver来检测到低出现什么问题,发现报错 Bad request 400 (\x00\x00\x80......)。
搜了一下,有人说是Django1.6需要设置ALLOWED_HOSTS,设置完之后还是同样的错误。
然后就各种搜。。。。在这里卡了有2~3天,所有能找的文章都找了就是不管用。
二、各种尝试
分别进行了如下尝试:
- 新建一个全新的django project,发现依然无法运行
- 直接runserver 0.0.0.0:8007,用IP访问,发现正常
- 将另一个域名解析过去进行访问,发现出错
得出结论,代码和域名解析都没问题,只能是nginx出问题了。
搜了各种nginx配置,比如编码啊,增加header size啊,甚至对比了新服务器和旧服务器的所有nginx文件,都不管用。
三、第一个坑
在测试的过程中发现一个问题,直接用IP可以访问,然后尝试了一下admin操作数据发现出错。后来猛然想到前面直接用mysqldump迁移的数据,可能会出问题。
搜了半天找到了django的数据迁移方法:
$ python manage.py dumpdata > xxx.json // 导出json格式数据
$ python manage.py syncdb
$ python manage.py loaddata xxx.json // 导入
使用时候发现导入出错,解决办法是导出时候加参数,不导出一些配置信息:
$ python manage.py dumpdata --exclude=contenttypes --exclude=auth.Permission > xxx.json
这样就可以正确迁移数据了。
四、剑走偏锋
现在又回到核心问题了,Bad request。
能找的办法都试过了,还是不行。猜测应该是nginx的fastcgi接口编码出现问题,导致传给django的url没有正确编码,所以django无法解析。
和徐景讨论了一下,他说既然IP直接访问可以,那不如就用反向代理好了,不要用fastcgi。
研究了一下,反向代理理论上确实可行。
nginx配置:
server {
listen 80;
server_name wx.aishougong.com;
location / {
proxy_pass http://127.0.0.1:8007;
}
}
django的server采用flup是不行的,因为flup使用fastcgi,但是反向代理并不是通过fastcgi通信。
所以这里采用gunicorn,一个wsgi服务器。
gunicorn使用很简单:
$ gunicorn myproject.wsgi:application
试了一下,可以成功访问了。
但是又有一个问题,这个命令无法后台执行。
解决办法是采用supervisor,这是一个可以后台运行任何命令的工具。
$ sudo apt-get install supervisor
安装完成后在 /etc/supervisor/conf.d/目录创建gunicorn.conf文件,内容:
[program:gunicorn]
command=gunicorn -b 127.0.0.1:8007 wx.wsgi:application
directory=/wx
user=nobody
autostart=true
autorestart=true
redirect_stderr=true
command就是刚才执行的命令,directory是执行路径。
保存文件,运行:
$ sudo supervisorctl reread
gunicorn: available
$ sudo supervisorctl update
这样gunicorn就运行起来了,再用微信试一下,正常了。
记录一下supervisor的常用命令:
$ sudo supervisorctl status hello
hello RUNNING pid 18020, uptime 0:00:50
$ sudo supervisorctl stop hello
hello: stopped
$ sudo supervisorctl start hello
hello: started
$ sudo supervisorctl restart hello
hello: stopped
hello: started
五、后记
写出来很简单,实际解决非常困难,耗费的时间超过10小时。好在最后还是解决了,又学到了不少东西。