基本环境
- 安装mysql
- python虚拟环境中安装你项目中的包
decode编码问题:'str' object has no attribute 'decode'
(困惑好久,因为部署到服务器端了,所以感觉程序没有问题了,后来开了DEBUG,找到了问题),/data/env/pyweb/lib/python3.7/site-packages/django/db/backends/mysql/operations.py in last_executed_query, line 146
decode->encode
-
mysqlclient版本问题
,需要注释源码(可能是当前版本的bug)
pip freeze >requirements.txt
打包本地安装的包文件(在本地环境中)
pip install - r requirements.txt
服务器中安装包(在服务器的虚拟环境中)
- 安装redis,修改redis.config文件(注释bind,守护进程启动,关闭保护模式)
安装FastDFS
- 安装fastDFS需要安装依赖的包
libfastcommon-master-master.zip
yum install unzip
unzip libfastcommon-master-master.zip
chmod +x make.sh
./make.sh
sudo ./make.sh install
- 安装fastdfs
https://my.oschina.net/harlanblog/blog/466487?fromerr=cqe6bTu2 - 修改配置文件
mv /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
mv /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
vim tracker.conf
< base_path /创建的空文件夹/tracker>
vim storage.conf
<base_path /创建的空文件夹/storage>
<storage_path0= /创建的空文件夹/storage>
<tracker_server=ip:22122> ip是你ifconfig得到的ip - 启动
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf
- 验证服务
ps aux|grep tracker&&storage
- 测试
修改clinet.conf 里面的 tracker_server 为ip:22122
vim filename.txt
fdfs_upload_file client.conf filename.txt
出现group....txt -———————— > 成功
FastDFS配合Nginx使用
Nginx安装及其模块的添加
- 下载Nginx压缩包
- 解压
- 执行预编译命令,指定安装的路径(--prefix= / 路径 / ),及添加模块操作(--add module=文件夹/src)
cd nginx目录中
./configure --prefix=/usr/local/nginx/ --add-module=fdfs_nginx模块目录/src
- 修改一些内容,否则在执行make时会报错(
Fatal error
)
chmod 777 /windowsfile/fastdfd_nginx_module/src/config
vim /windowsfile/fastdfd_nginx_module/src/config
下面的内容发生了更改
ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/"
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
- 进入nginx源码目录
./configure --add-module= /windowsfile/fastdfs-nginx-module/src
make
make install
- 未出现什么异常,添加第三方模块完成。
- 编译安装
make
make install
- 模块要和nginx的版本对应,否则会报错
https://github.com/downgoon/hello-world/wiki/FastDFS-Install-&-Upload-&-Download
Nginx相关的配置
- fdfs模块的配置
cp /windowsfile/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
vim mod_fastdfs.conf
<timeout为10>
<tracker-server ip:22122>
<url_has_group_name为 true> -
nginx.conf
- 启动nginx后就可以在浏览器中显示图片了
目前本地的程序已经可以基本运行了,因为redis,fdfs就位,差celery异步。下一步就是在服务器运行程序。
uwsgi 配置
- 在项目中创建
uwsgi.ini
,内容
[uwsgi]
# 直接作为web服务器使用 python manage.py runserver ip:port
# http=127.0.0.1:8080
socket = 127.0.0.1:8080
# 项目的文件目录
chdir=/项目目录
# wsgi文件在你的项目目录的哪里 基于上面的目录
wsgi-file=daily_fresh/wsgi.py
processes=4
threads=2
master=True # 有主进程
# 保存主进程的进程号
pidfile=uwsgi.pid
# 作为守护进程,并保存日志
daemonize=uwsgi.log
# 虚拟环境的目录
virtuaenv=/虚拟环境的目录
- 启动:
uwsgi --ini /配置文件目录
- 停止:
uwsgi --stop uwsgi.pid路径
例如:uwsgi --ini uwsgi.ini;
uwsgi --stop uwsgi.pid或者 pkill -f uwsgi -9
uwsgi + Nginx(做)
- 将项目拷贝到服务器,修改
DEBUG = False,ALLOWED_HOSTS = ['*']
,并在settings中设置STATIC_ROOT = '/data/www/static'
指定静态文件收集的目录(这个目录应该是已创建的) - 这个文件夹要搞一下权限
chmod 777 /data/www/static
- 改一下mysql
否则会提示mysqlclient错误: /data/env/pyweb/lib/python3.7/site-packages/django/db/backends/mysql/base.py,修改环境下的lib/python3.7/site···文件,或者将本地已经改好的base.py复制过去 - 执行 收集静态文件
python manage.py collectstatic
1750 static files copied to '/data/www/static'.成功
静态文件已经收集好了,剩下要让nginx显示 - 配置nginx.conf
location / {
inlcude uwsgi_params; # 参数也要包含
uwsgi_pass 127.0.0.1:8080; # 转交给uwsgi
}
location /static {
alias /data/www/static/; # 指定静态文件的目录
}
- 重启nginx
sbin/nginx -s reload
nginx还未完成
celery的配置
- celery任务中有导入app的模块,所以需要django的环境
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE','dailyfresh.settings')
#或者os.environ['DJANGO_SETTINGS_MODULE'] ='daily_fresh.settings')
django.setup()
- 进入虚拟环境执行,报错(goods/admin.py)can't import index_html
理论上应该是没有问题,但是不能导入,就是时机不对,太早了,所以在使用到这个函数的时候在导入,写在里面就好了
class BaseAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
from celery_tasks.tasks import generate_static_index_html
generate_static_index_html.delay()
cache.delete('index_page_data')
def delete_model(self, request, obj):
super().delete_model(request, obj)
from celery_tasks.tasks import generate_static_index_html
generate_static_index_html.delay()
cache.delete('index_page_data')
- 没有haystack.backends.whoosh_cn_backend'
这个是自己修改的,所以将本地的拷贝到服务器中haystack中的文件夹中 - 启动celery时遇到错误,
无法连接redis://ip:6379
,把ip改为了本机ip改为内网地址应该成功,我该为了127.0.0.1成功。 - 再次启动成功,但是执行任务时出错,
静态首页时报错,应该返回一个dict,而不是一个request对象
,将context = 字典后,不对他进行封装。 - 遇到ImageFilefield Error,模板中的问题,将模板文件中的图片image.url,去掉了url。暂时好了,但是生成的页面图片地址不对,后来知道是fdfs_client的原因,下面也有。
- stmp邮箱遇到错误,无法连接到stmp
将settings文件中的EMAIL_USE_TSL = False改为 EMAIL_USE_SSH = True
成功发送邮件。
uwsgi + Nginx(释)
- 在将项目拷贝到服务器之前,改
DEBUG = False,ALLOWED_HOSTS = ['*']
,这样在服务器端静态文件不会生效,需要用到nginx
- 思路: 1. 用户访问一个地址,由nginx接受参数,并判断是静态请求还是动态请求
这步判断就是nginx的路由匹配
location /url/ { }
- 如果是静态请求,就是请求了一些图片,css,js等资源,我们实现把这些资源放在一个文件中,并设置nginx的路由匹配,将匹配结果导向我们的文件位置。
- 如果是动态请求,那么就转交给uwsgi,让uwsgi在调用application() 访问django系统,系统返回参数给uwsgi,再通过nginx返回到用户界面。
nginx配置文件,里面的http{}
中全是一些serve{}
。
有listen
:监听的端口号,
server_name
:监听的ip地址
location ‘url’{ }
:路由,括号里面类似于django的urls。
静态请求
1 如果像直接返回静态文件,不提交到uwsgi服务器,那么里面直接写本机中的文件路径,新建一个存放静态文件的路径。/data/www/daily_fresh/static
,然后在nginx.conf中指定当访问/static
路径时,就去找/data/www/daily_fresh/static
目录
location /static {
# 指定存放静态文件的目录
alias /data/www/daily_fresh/static
}
在setting的文件中指定STATIC_ROOT的值为刚才的路径/data/www/daily_fresh/static
,
执行 python manage.py collectstatic
收集静态文件。
权限不够的话, chmod 777 /data/daily_fresh/static/
1.2 当用户请求的静态文件不在此电脑上时可以,可以通过ip访问到另一nginx的上的静态文件
location = / {
指定存放静态文件nginx的ip地址,及端口,没写就是默认80
proxy_pass http://ip:port;
}
动态请求
- 如果是要提交给uwsgi服务器,同时还要提交传入的参数给uwsigi, 就需要uwsgi的端口号和地址。
# 包含uwsgi的请求参数
include uwsgi_params;
# 转交给 uwsgi 的ip和端口
uwsgi_pass 127.0.0.1:8080;
配置nginx的时候,小心分号,少写会报错。
项目总体
每一个部分都可以在不同的电脑上。
- django项目跑在uwsgi服务器上,可以在项目中多创建几个uwsgi.ini,注意其中的socket端口不能相同,还有就是uwsgi.pid和log的名字也要变化
- 静态页面的服务器和应用服务器时分离的,实现了前后端分离。
- 在调度服务器中可以通过ip:port访问静态文件。
- 调度服务器中负载均衡,要修改conf文件,加上
upstream somename{
server ip:port1
server ip:port2
当用户访问时,会轮流执行
}
之前是将请求直接返回给了uwsgi,现在,较给somename,让他决定哪个应用服务器执行。
**
location / {
include uwsgi_parms;
uwsgi_pass somename;
}
**
- mysql,fstdfs,redis也可不在同一台电脑中,通过ip:port连接。
其中fdfs的访问要通过nginx实现,让他监听网站的某个端口来实现上传和下载。
- 部署时,先检查项目跑起来有没有问题
python manage.py runserver
,如果有问题就是项目中存在问题,可能是你在本地的改了配置文件,但是在服务器中虚拟环境中没有更改,例如mysqlclient的问题
,decode的问题
,haystack中添加了配置的文件
- 上一步完成就添加一个uwsgi文件
- 修改nginx配置文件
- 让uwsgi的配置文件生效
- 启动nginx
- celery中的任务,要填加上django的环境
在tasks中的前面要加上django启动时的环境,但是启动时的环境导入这任务中的函数就会出错,报import异常,所以要把import放在里面,什么时候用,什么时候import。
出现的问题
TypeError: context must be a dict rather than RequestContext:
这个问题是django版本的问题,出现在生成静态首页的位置,我们需要得到html页面,并保存在本地,而不需要返回
# 使用模板
# 加载模板文件
temp = loader.get_template('static_index.html')
# 定义模板上下文
context = RequestContext(request,context)
# 模板渲染
static_index_html = temp.render(context)
# 生成首页对应的静态文件
save_path = os.path.join(settings.BASE_DIR, 'static/index.html')
with open(save_path,'w') as f:
f.write(static_index_html)
问题的关键是context必须是一个字典
继续上面的nginx
- 把项目部署到服务器上时,收集了静态文件到一个目录
/data/www/daily_fresh/static
这个不是我的项目目录 - 然后在nginx的配置中,匹配/static的就去找
/data/www/daily_fresh/static/
, 匹配/的就转交给uwsgi :# 包含uwsgi的请求参数
include uwsgi_params;
# 转交给 uwsgi 的ip和端口
uwsgi_pass 127.0.0.1:8080;
但是始终不能访问,位置也换过,文件夹的权限也改过,这里猜想可能是因为这里的static并没有被访问,因为没有给项目中的static配置,所以访问不到。但是静态页面也应该出现个画呀,不知道是什么问题。
于是我采取了曲线救国的策略,又配置了一台nginx server
server 配置81端口
location / {
root /data/daily_fresh/static/; #我的项目路径
index index.html index.htm
}
location /static { # 右边没有/
alias /data/daily_fresh/static/; #我的项目路径
}
启动这台服务器,然后访问网站的81端口(在服务器中打开端口,重启防火墙,在阿里云客户端添加81端口),成功。
主nginx精确匹配 / 时,转交给这台nginx
nginx.conf
user root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 8888;
server_name 47.100.179.209;
location ~/group[0-9]/ {
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 81;
server_name 47.100.179.209;
location / {
# autoindex on;
root /data/daily_fresh/static/;
index index.html index.htm;
}
location /static{
alias /data/daily_fresh/static/;
}
}
# upstream daily_fresh{
# server 127.0.0.1:8080;
# server 127.0.0.1:8081; # 将下面的uwsgi_pass 中的127.0.0.1换成daily_fresh
# } 前提是有两个uwsgi.ini文件,启动两个uwsgi,nginx 负责发牌式的负载均衡
server {
listen 80;
server_name 47.100.179.209;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8080;
#uwsgi_pass daily_fresh;
}
location = /{
proxy_pass http://47.100.179.209:81;
}
location /static{
alias /data/www/static/;
}
}
出现的问题
图片类型没有发布,ImageFileField is not 发布
- 使用celery发布任务时,得到错误,
ImageFileField is not 发布
,将页面中的sku.image.url改为sku.image后可以正常的发布任务,可以正常生成静态页面,但是有问题,路径不太对,好像是缺了端口还是什么,反正不能正常显示图片。最后想到在windows中安装的fdfs_client应该是不匹配linux系统的,而在执行pip install -r requirement.txt
时,安装的是windows版本的fdfs_client,所以卸载,傻瓜安装不放心,所以下载安装包安装,cd 进去,python setup.py install ,发布任务就没发现错误
自己傻了
- 一开始访问的fdfs地址就不对,还有静态文件的目录也不对,查验后使用的之前的index.html,使用自己生成的静态文件后成功
总结:
出现问题后程序的问题不大,前提是在windows端出现的错误改了之后(指改mysqlclient,django/db里面的源码)
- 仔细看看有没有操作失误,指在各种conf中有没有配置错误,拼写错误,拼写错误,拼写错误。。。
- 如果是静态文件,打开F12看看出现什么问题,路径错误就去模板html中再看看,settings中的几项配置STATICFILES_DIRS,STATIC_URL,STATIC_ROOT看看,多斜杠,少斜杠
- 打开DEBUG看看有什么错误,这个是最管用的,记得把ALLOW_HOSTS=[‘*’]
- linux和windows的不兼容问题,出问题的是什么插件,就去百度下有没有类似的错误,有没有相关的资料。
5.再来一遍。