记一次非常痛苦的解决问题过程

零、背景

 

之前给微信公众号“爱手工”做过微信后台,最近由于服务器要更换,所以需要将后台迁移到新服务器上。

 

 

 

一、问题出现

 

本来以为很轻松就能搞定,安装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小时。好在最后还是解决了,又学到了不少东西。

posted @ 2014-03-11 11:11  numbbbbb  阅读(535)  评论(0编辑  收藏  举报