nginx + uwsgi +sqlite3 + linux

部署方式:

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()错误返回。

 

 

 

 

 

原文地址:https://www.cnblogs.com/zy09/p/15339971.html