部署方式:1.升级python 

CentOS 7 中默认安装了 Python,版本比较低(2.7.5),为了使用新版 3.x,需要对旧版本进行升级。

由于很多基本的命令、软件包都依赖旧版本,比如:yum。所以,在更新 Python 时,建议不要删除旧版本(新旧版本可以共存)

查看 Python 版本号

当 Linux 上安装 Python 后(默认安装),只需要输入简单的命令,就可以查看 Python 的版本号:



# python -V
Python 2.7.5


 使用 wget 将安装包都下载到 /Downloads/



[root@localhost Downloads]# ll
总用量 40932
drwxr-x---. 18 root root 4096 9月 26 12:22 Python-2.7
-rw-r--r--. 1 root root 14026384 9月 26 12:22 Python-2.7.tgz
drwxr-xr-x. 19 root root 4096 9月 26 14:13 Python-3.7.0
-rw-r--r--. 1 root root 22745726 9月 26 12:21 Python-3.7.0.tgz
-rw-r--r--. 1 root root 41313 9月 26 12:22 python-iniparse-0.4-18-omv4002.noarch.rpm
-rw-r--r--. 1 root root 39780 9月 26 12:22 python-sqlite-1.1.7-1.2.0.99_4.el4.at.x86_64.rpm
drwxr-xr-x. 5 1000 1000 4096 9月 26 14:56 sqlite-autoconf-3300100
-rw-r--r--. 1 root root 2848951 9月 26 12:22 sqlite-autoconf-3300100.tar.gz
drwxrwxr-x. 20 30001 30001 4096 6月 20 2020 uwsgi-2.0.19.1
-rw-r--r--. 1 root root 811149 9月 26 12:22 uwsgi-2.0.19.1.tar.gz
-rw-r--r--. 1 root root 1298856 9月 26 12:22 yum-3.4.3-168.el7.centos.noarch.rpm
-rw-r--r--. 1 root root 28348 9月 26 12:22 yum-metadata-parser-1.1.4-10.el7.x86_64.rpm
-rw-r--r--. 1 root root 35216 9月 26 12:22 yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch.rpm
[root@localhost Downloads]#


 

1、环境准备:先安装准备环境



yum install gcc gcc-c++ automake pcre pcre-devel zlip zlib-devel openssl openssl-devel


 

 解压



# tar -zxvf Python-3.7.0.tgz


 

 

安装配置

进入解压缩后的目录,安装配置:



# cd Python-3.7.0/
# ./configure make && make install


验证

安装成功以后,就可以查看 Python 的版本了:



# python -V
Python 2.7.5
# python3 -V
Python 3.7.0


 

一个是旧版本 2.x,另外一个是新版本 3.x。

注意:在 /usr/local/bin/ 下有一个 python3 的链接,指向 bin 目录下的 python 3.7。

设置 3.x 为默认版本

查看 Python 的路径,在 /usr/bin 下面。可以看到 python 链接的是 python 2.7,所以,执行 python 就相当于执行 python 2.7。

 

将原来 python 的软链接重命名:



# mv /usr/bin/python /usr/bin/python.bak


将 python 链接至 python3:



# ln -s /usr/local/bin/python3 /usr/bin/python


这时,再查看 Python 的版本:



# python -V
Python 3.7.0


 

 输出的是 3.x,说明已经使用的是 python3了。

 

配置 yum

升级 Python 之后,由于将默认的 python 指向了 python3,yum 不能正常使用,需要编辑 yum 的配置文件:



# vi /usr/bin/yum


 

同时修改:



# vi /usr/libexec/urlgrabber-ext-down


 

将 #!/usr/bin/python 改为 #!/usr/bin/python2.7,保存退出即可。


2.升级 sqlite3 解决Django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17)。

CentOS 自带 3.7.17 Django,不支持。它必须高于 3.9.0。如果你想用SQLite3作为数据库,是没有办法升级的。如果是我,我不会用SQLite3,而是用mysql


升级很简单:


1.下载SQLite3最新包



https://www.sqlite.org/download.html

wget https://www.sqlite.org/2021/sqlite-autoconf-3350500.tar.gz



2.编译安装

tar xf https://www.sqlite.org/2021/sqlite-autoconf-3350500.tar.gz
cd sqlite-autoconf-3350500
./configure --prefix=/usr/local/ && make && make install


 

 

3.改变原来的SQLite3命令

首先检查SQLite3在哪个目录中有可执行文件



[root@localhost Downloads]# whereis sqlite3
sqlite3: /usr/bin/sqlite3 /usr/local/bin/sqlite3 /usr/share/man/man1/sqlite3.1.gz
[root@localhost Downloads]# sqlite3 -V


 

 

发现/usr/bin/SQLite3是旧的,3.7.17。如果您不确定,请执行它

/usr/bin/sqlite3 –version

然后替换旧版本



mv /usr/bin/sqlite3 /usr/bin/sqlite3_3.7.17
ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3


 

 

4.更改库路径

很多小伙伴去上面测试了一下。他们发现在执行python manage.py runserver 8080时还是报同样的错误,原因是django读取了旧库,可以自行验证



(python36) [root@george servermonitor]# python 
Python 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623
(Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
> >>> sqlite3.sqlite_version
> '3.7.17'
>>> .exit


 

 

修改库变量



export LD_LIBRARY_PATH="/usr/local/lib/"


 永久修改



修改~/.bashrc或~/.bash_profile或系统级别的/etc/profile
1. 在其中添加例如
export LD_LIBRARY_PATH="/usr/local/lib/"
2. source .bashrc (Source命令也称为“点命令”,也就是一个点符号(.)。source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录)


 

 测试 



python manage.py runserver 8080


 

 3.安装 uwsgi

Django的主要部署平台是WSGI,它也是Python的标准web服务器和应用。

uWSGI是实现了WSGI协议的WSGI服务器。

uWSGI 是一个快速的、自我驱动的、对开发者和系统管理员友好的应用容器服务器,完全由 C 编写。

uWSGI的官网地址:https://uwsgi-docs.readthedocs.io/en/latest/index.html

根据血和泪的经验教训,请确保安装的是最新版本的uwsgi,否则可能出现各种坑。

所以不建议使用:​​pip3 install uwsgi​​(不一定是最新版)

不建议使用:​​pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz​​(也不一定是最新版)

而是建议到https://uwsgi-docs.readthedocs.io/en/latest/Download.html页面,下载​​Stable/LTS​​版本的源文件。

为什么要最新版?因为现在的官方教程和相关技术文章全是以新版编写的,很多参数名,用法有较大改变。用旧版,你可能连跑都跑不起来。

这里使用进行安装



pip3 install uwsgi


 

安装完毕后,尝试运行一下uwsgi:



root@kube mylab]# uwsgi
*** Starting uWSGI 2.0.19.1 (64bit) on [Fri Jan 15 15:14:13 2021] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-39) on 13 January 2021 07:53:36
os: Linux-3.10.0-1062.9.1.el7.x86_64 #1 SMP Fri Dec 6 15:49:49 UTC 2019
nodename: kube.master
machine: x86_64
....


 



uwsgi --python -version


 

测试 uwsgi



在项目目录执行
uwsgi --http 192.168.2.2:8000 --file network/wsgi.py --static-map=/static=/opt/project_network/network/network/static


 

配置uwsgi

在项目目录下 mkdir script 文件



[root@localhost script]# pwd
/opt/project_network/script


 



[root@localhost script]# cat uwsgi.ini 
[uwsgi]
#项目根目录
chdir = /opt/project_network/network/
# 指定wsgi模块下的application对象,就是调用 mylab.wsgi 文件中的 application 对象
module = network.wsgi:application
#wsgi-file = /opt/project_network/network/network/wsgi.py
#//对本机8000端口提供服务
#http-socket = 192.168.2.2:8888
socket = /opt/project_network/script/network.sock
#//主进程
master = true


# 以上4个是核心配置项

#vhost = true //多站模式
#no-site = true //多站模式时不设置入口模块和文件
#workers = 2 //子进程数
#reload-mercy = 10
#vacuum = true //退出、重启时清理文件
max-requests = 1000
limit-as = 512
buffer-size = 30000
pidfile = /opt/project_network/script/uwsgi9090.pid
# //pid文件,用于下脚本启动、停止该进程


#日志文件
daemonize = /opt/project_network/script/uwsgi.log
#不记录正常信息,只记录错误信息
#disable-logging = true
[root@localhost script]#


 

相关命令:



[root@localhost script]# uwsgi --ini uwsgi.ini   #启动
[uWSGI] getting INI configuration from uwsgi.ini
[root@localhost script]# uwsgi --stop uwsgi9090.pid #停止
[root@localhost script]#


 

 

相关问题: 出现了 getway 502 报错 ,最终原因是 一定要确认前面的 python3 sqlite3 成功替换,nginx 调用出问题,可以根据uwsgi.log 排查

 

 4.安装 nginx 

下载 nginx repo 文件



[root@localhost script]# cat /etc/yum.repos.d/nginx.repo 
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[root@localhost script]#


 

 



yum update
yum install nginx -y


 



[root@localhost script]# cat /etc/nginx/conf.d/network.conf 
server {
#如果要使用 https 请参考nginx 添加证书的博客
listen 80; #区别于 uwsgi 端口,不然会造成端口冲突
#listen [::]:8090; #监听 ipv6 端口
error_log /opt/project_network/script/nginx_error.log;
access_log /opt/project_network/script/nginx_access.log main;
charset utf-8;
gzip on;
server_name 192.168.2.2; #当访问此名称时 ,nginx 会进行server_name 进行匹配
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

location / { #匹配 / 目录
include uwsgi_params; #导入 uwsgi_params 文件
uwsgi_pass unix:/opt/project_network/script/network.sock; #使用 uwsgi_pass 参数将数据传递给 uwagi 应用服务器,使用 uwsgi.ini 中定义的 sock 文件


}
location /static/ { #匹配static 静态文件的 ,进行别名处理

alias /opt/project_network/network/network/static_all/;
index index.html index.htm;

}


}
[root@localhost script]#


 查看 sock 



[root@localhost script]# netstat -ap --unix |grep uwsgi #netstat -ap --unix #显示处于监控状态的unix socket,-a显示所有state状态的链接,因为默认不显示处于listening状态的。-p显示与socket有关的pid/programe name
unix 2 [ ACC ] STREAM LISTENING 18516 1158/uwsgi /opt/project_network/script/network.sock
unix 3 [ ] STREAM CONNECTED 18532 1158/uwsgi
unix 3 [ ] STREAM CONNECTED 18529 1158/uwsgi
unix 3 [ ] STREAM CONNECTED 18530 1158/uwsgi
unix 3 [ ] STREAM CONNECTED 18531 1158/uwsgi
[root@localhost script]#


 

 

 

重要生产操作:



# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

#静态资源的访问
# STATIC_URL 引用位于 STATIC_ROOT 中的静态文件时要使用的 URL。
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static_all')

#这个配置定义了静态文件应用在启用 FileSystemFinder 查找器时将穿越的额外位置,例如,如果你使用 collectstatic 或 findstatic 管理命令或使用静态文件服务视图。
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]


 



[root@localhost network]# python manage.py collectstatic   #会将 admin 文件  和 STATICFILES_DIRS 定义的目录合并为 static_all 中 , 因此 nginx 中的
alias /opt/project_network/network/network/static_all/;   这里不是  static 结尾


 

​collectstatic​​​​¶​

​django-admin collectstatic​​​​¶​

将静止文件收集到​​STATIC_ROOT​​中。

 

项目目录结构



[root@localhost opt]# tree -L 3
.
└── project_network
├── network
│ ├── db.sqlite3
│ ├── __init__.py
│ ├── logs
│ ├── manage.py
│ ├── network
│ ├── __pycache__
│ └── requirement.txt
└── script
├── network.sock
├── nginx_access.log
├── nginx_error.log
├── uwsgi9090.pid
├── uwsgi.ini
└── uwsgi.log

6 directories, 10 files
[root@localhost opt]#


  

 

 uwsgi 标准配置 https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/



[uwsgi]
strict = true
master = true
enable-threads = true
vacuum = true ; Delete sockets during shutdown
single-interpreter = true
die-on-term = true ; Shutdown when receiving SIGTERM (default is respawn)
need-app = true

disable-logging = true ; Disable built-in logging
log-4xx = true ; but log 4xx's anyway
log-5xx = true ; and 5xx's

harakiri = 60 ; forcefully kill workers after 60 seconds
py-callos-afterfork = true ; allow workers to trap signals

max-requests = 1000 ; Restart workers after this many requests
max-worker-lifetime = 3600 ; Restart workers after this many seconds
reload-on-rss = 2048 ; Restart workers after this much resident memory
worker-reload-mercy = 60 ; How long to wait before forcefully killing workers

cheaper-algo = busyness
processes = 128 ; Maximum number of workers allowed
cheaper = 8 ; Minimum number of workers allowed
cheaper-initial = 16 ; Workers created at startup
cheaper-overload = 1 ; Length of a cycle in seconds
cheaper-step = 16 ; How many workers to spawn at a time

cheaper-busyness-multiplier = 30 ; How many cycles to wait before killing workers
cheaper-busyness-min = 20 ; Below this threshold, kill workers (if stable for multiplier cycles)
cheaper-busyness-max = 70 ; Above this threshold, spawn new workers
cheaper-busyness-backlog-alert = 16 ; Spawn emergency workers if more than this many requests are waiting in the queue
cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue


 

 

下面告警需要关闭 selinux 



getenforce
setenforce 0 关闭
setenforce 1 开启


 



2021/09/26 21:30:57 [crit] 1463#1463: *19 connect() to unix:/opt/project_network/script/network.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.2.254, server: 192.168.2.2, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/opt/project_network/script/network.sock:", host: "192.168.2.2"
2021/09/26 21:30:57 [crit] 1463#1463: *19 connect() to unix:/opt/project_network/script/network.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.2.254, server: 192.168.2.2, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/opt/project_network/script/network.sock:", host: "192.168.2.2"


 

 

附件:

inux使用netstat命令监控unix domain socket(unix socket,.sock文件)状态

UNIX Domain Socket IPC

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。

使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。