首先讲讲我的配置清单🧾
宿主机 OS: CentOS 7
Nginx 版本:1.16.1
Docker 版本: 19.03.13
Docker 容器零碎: CentOS 7
Python 虚拟环境治理: Anaconda
Python 版本: Python 3.7
选用的后端框架: Fastapi
Python 操作 PostgreSQL: Psycopg2
(毋容置疑)
数据库: PostgreSQL 12
(毋容置疑 + 1)
宿主机中须要做的配置
1. 装置 & 配置 Nginx
大部分内容出自此链接🔗:https://juejin.im/post/684490…
# 装置 Nginx
yum -y install nginx
# 卸载 Nginx
yum remove nginx
# 设置开机启动,倡议关上
systemctl enable nginx
# 启动 nginx 服务,装置后需运行
systemcrl start nginx
# 进行 nginx 服务
systemcrl stop nginx
# 重启 nginx 服务
systemcrl restart nginx
我的 Nginx 配置,以下仅为局部配置,可下载一键脚本进行配置。
如果不晓得本人的 Nginx 配置的文件地位在哪,可应用 systemctl status nginx
查看。
# 编辑的文件
# 我的文件地址是
# vi /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name www.xxx.xxx;
rewrite ^(.*)$ https://$host$1 permanent;
}
server {
listen 443 ssl http2;
server_name www.xxx.xxx;
root /etc/nginx/html;
index index.php index.html;
location / {try_files $uri $uri/ /index.php?$args;}
# fastapi main
location /helloworld {proxy_pass http://127.0.0.1:8011;}
# fastapi docs
location /docs {proxy_pass http://127.0.0.1:8011/api/docs;}
}
2. 装置 & 配置 Docker
# 装置 Docker
yum -y install docker
# 启动 Docker 后盾服务,装置完后需运行
systemctl start docker
# 开机自启动 Dokcer,倡议开启
systemctl enable docker
# 查看 Dokcer 运行信息
systemctl status docker
# 重启 Docker 服务
systemctl restart docker
# 检测 Docker 是否失常装置,尝试跑一个叫 hello-word 的镜像
docker run hello-world
# 查看是存在 hello-world 镜像,如果存在,则胜利
docker images
# 拉取 CentOS 镜像,留神 ':' 前面带的是零碎版本,# 同样的 docker images 能够查看是否存在 centos 这个镜像
docker pull centos:7.8.2003
# 运行 docker centos 的时候,# 肯定要留神凋谢端口,以不便容器内的 Fastapi 应用
docker run -ti -d -p 80:80 -p 8011:8011 --privileged=true centos:7.8.2003 /usr/sbin/init
# 查看所有镜像的信息,方便使用 container id 进入
docker ps -a
# 先执行 attach 命令,以取得 systemctl 权限
docker attach docker_container_id
# 下次进入 docker 就不是下面那句 attach 命令了,而是
docker exec -it docker_container_id /bin/bash
# 所以须要 docker ps -a 查看 container id
! 重要!:之后进入这个容器就不能用 docker attach docker_container_id
了,但为了保险,先 attach
一次,以取得容器内 CentOS 7
执行 systemctl
命令的权限
# 而后关掉终端或命令行,开启新的终端或命令行,这次换另外一条命令进入 虚拟机
docker exec -it docker_container_id /bin/bash
对于 CentOS 7 装置 Docker 更具体的信息:https://www.jianshu.com/p/3a4…
对于 Docker 装置 CentOS 7 及根本配置:https://victorzhong.github.io…
容器内虚拟机须要做的配置
1. 装置 & 配置PostgreSQL 12
记得在 sql shell
外面的命令,结尾都要加上 ;
分号。
# 先装置 yum 的下载源,即装置 epel-release,# 下载之后,就能够间接跳到 装置 PostgreSQl 12 那一步
#(还有其它的国内源请看:https://www.jianshu.com/p/541c737bc947)yum -y install epel-release
# 如果抉择不装置 yum 下载源 则应用上面的命令
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 装置 PostgreSQL 12
yum install -y postgresql12 postgresql12-server
# 初始化数据库
/usr/pgsql-12/bin/postgresql-12-setup initdb
# 启动 PostgreSQL 服务
systemctl start postgresql-12
# 设置 PostgreSQL 服务为开机启动
systemctl enable postgresql-12
# 查看 PostgreSQL 服务状态
systemctl status postgresql-12
# 进入 PostgreSQL 命令行
su postgres
# 启动 SQL Shell
psql
! 重要!,此时先不要退出 sql shell
!接下来,可输出 \l
查看 DataBase
的 Encoding
,假若 Encoding
不为 UTF8
,插入中文值到数据库的时候,会出错!
请先不要急着卸载或执行破坏性命令(血与泪的教训),请依照程序执行上面的命令,以更改 DataBase
的 Encoding
。
这些命令全都要在 SQL Shell
外面执行!记得 ;
分号结尾,如果还是忘了,按 ctrl / command + c 能够退回到初始状态。
# 先切换 DataBase
\c template0;
# 将 template1 的 datistemplate 改为 false
update pg_database set datistemplate = FALSE where datname = 'template1';
# 删除 template1 DataBase
drop database template1;
# 从新创立 template1 DataBase 以 UTF8 编码
create database template1 with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template0;
# 从新将 template1 的 datistemplate 改为 true
update pg_database set datallowconn = TRUE where datname = 'template1';
# 接下来切换到 template1 Database
\c template1;
# 反复步骤,批改 template0 的 datistemplate
update pg_database set datistemplate = FALSE where datname = 'template0';
# 删除 template0 DataBase
drop database template0;
# 从新创立 template0 DataBase 以 UTF8 编码
create database template0 with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template1;
# 从新将 template0 的 datistemplate 改为 true
update pg_database set datallowconn = TRUE where datname = 'template0';
! 重要!,切勿真的删除 template0
& template1
这两个数据库
# postgres 数据库,反复以上步骤,即可把 Encoding 改为 UTF8,不再赘述正文
\c template1;
update pg_database set datistemplate = FALSE where datname = 'postgres';
drop database template0;
create database postgres with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template0;
update pg_database set datallowconn = TRUE where datname = 'postgres';
\c postgres;
# 再次输出 \l 查看 Encoding,确保批改胜利。
当执行了破坏性命令,例如:yum remove postgresql12 postgresql12-server
。
并从新执行了 yum install postgresql12 postgresql12-server
后,执行初始化数据库命令时会出错,
即当在 [root@xxx /]#
状态下执行 /usr/pgsql-12/bin/postgresql-12-setup initdb
命令时会呈现,该文件夹 📁 不为空的报错。
此时需执行:rm -rf /var/lib/pgsql/12/data/
删除该文件夹。
而后从新执行 /usr/pgsql-12/bin/postgresql-12-setup initdb
命令即可。
# 批改 postgres 数据库明码
ALTER USER postgres WITH PASSWORD 'NewPassword';
! 重要!,容许所有 IP 拜访,我的配置
# 批改配置文件
vi /var/lib/pgsql/12/data/pg_hba.conf
# 将 ipv4 上面的内容改为
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# 重启 postgresql-12 服务,留神⚠️肯定要带上 -12
systemctl restart postgresql-12
# 如果须要退出 postgres=# 或 bash-4.2$ 的状态
间接输出 exit 按回车即可。
PostgreSQL 12
装置 & 配置结束
PostgreSQL
批改数据库编码方式代码源自🔗:https://www.jianshu.com/p/628…
更具体的信息可点击此链接🔗(大部分内容也源自此链接):https://ken.io/note/centos7-p…
2. 装置 & 配置 Anaconda
以下内容大部分来自此链接🔗:https://juejin.im/post/685457…
# 下载 wget
yum -y install wget
# 配置 下载源
yum -y install perl
# 下载 Anaconda
wget https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh
# 装置 Anaconda
bash Anaconda3-5.3.1-Linux-x86_64.sh
# 进入安装程序,提醒输出“ENTER”持续:Please, press ENTER to continue
>>> ENTER
# 输出 yes 确认承受许可协定
Do you accept the license terms? [yes|no]
[no] >>> yes
# 确认 Anaconda 的装置地位, 可改可不改
Anaconda3 will now be installed into this location:/root/anaconda3 -
Press ENTER to confirm the location - Press CTRL-C to abort the installation -
Or specify a different location below[/root/anaconda3] >>> /opt/anaconda3
# 装置实现后,呈现询问是否在用户的.bashrc 文件中初始化 Anaconda3 的相干内容,此处选 yes
Do you wish the installer to initialize Anaconda3by running conda init? [yes|no][no] >>> yes
装置实现 ✅,Anaconda
的一些根底命令:
# 执行下:source ~/.bashrc,# 应用 conda 命令时就不会报 conda command not found 了
# 创立一个 Python3.7 版本的虚拟环境
conda create --name fastapienv python=3.7
# 删除虚拟环境命令
conda remove -n fastapienv --all
# 激活虚拟环境,可间接激活虚拟环境,无需先停用以后虚拟环境
conda activate fastapienv
# 停用虚拟环境
conda deactivate fastapienv
# 查看以后虚拟环境已装置的包
conda list
# conda 安装包命令,如果是装置 fastapi
conda install fastapi
# 当 conda install 无奈装置某个包时,通过查问 pip 的门路,# 如果有显示以后虚拟环境名,则能够应用 pip 装置 Python 包,看是否能装上
whereis pip
pip install fastapi
# 如果 pip install / coonda install 都无奈装置,则须要下载源码包,应用命令解压装置。
解决每次进入虚拟机时,Anaconda
虚拟环境皆为 base
的问题
(源自此链接🔗:https://www.cnblogs.com/alpha…)
# 批改 ~/.bash_profile 文件,有时 ~/.bashrc 文件里也会有此配置
export PATH="~/anaconda/envs/your_env_name/bin:$PATH"
# your_env_name 是你自定义的环境名
# 批改 ~/.bashrc 文件
conda activate your_env_name
# "your_env_name" 就是你的环境名
# 更新配置
source ~/.bashrc
source ~/.bash_profile
# 设置好后,返回到刚进入虚拟机的状态 [root@xxx /]#,# 执行以下命令以进行 base 虚拟环境自启动
conda config --set auto_activate_base false
我的配置:
# vi ~/.bashrc
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/root/anaconda3/bin/conda''shell.bash' 'hook' 2> /dev/null)"
if [$? -eq 0]; then
eval "$__conda_setup"
else
if [-f "/root/anaconda3/etc/profile.d/conda.sh"]; then
. "/root/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/root/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
conda activate fastapienv
# <<< conda initialize <<<
# vi ~/.bash_profile
# PATH=$PATH:$HOME/bin
PATH="~/anaconda3/envs/fastapienv/bin:$PATH"
export PATH
export LANG="en_US.UTF-8"
Anaconda
配置结束
我的 Anaconda
虚拟环境 fastapienv
还须要装置的包
# 除了根本的包以外
还装置了:fastapi
uvicorn
psycopg2
# 小程序解密用
pycryptodome
3. 装置 & 配置 & 启动一个 Fastapi
根底后端
fastapi 官网中文链接🔗:https://fastapi.tiangolo.com/zh/
执行上面的步骤前,必须先装置好 fastapi & uvicorn & psycopg2
# 找个你喜爱的门路,(我喜爱 /tmp/)创立 main.py 文件,键入以下代码:from typing import Optional
from fastapi import FastAPI
# 跨域
from fastapi.middleware.cors import CORSMiddleware
import psycopg2
import psycopg2.extras
app = FastAPI()
# 跨域配置
origins = [
"http://localhost.tiangolo.com",
"https://localhost.tiangolo.com",
"http://localhost",
"http://localhost:8080",
"http://127.0.0.1",
"http://127.0.0.1:8080",
"*"
]
# 跨域配置
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
# 个别都是 5432 端口,下文会提及如何查问
conn = psycopg2.connect(database="postgres", user="postgres", password="Your_Pass_Word", host="127.0.0.1", port="5432")
# 这段代码很要害,下文会解释
cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
@app.get("/")
def read_root():
return {"Hello": "World"}
# 创立员工数据表
@app.get("/create/stafftable")
def create_staff_table():
sql = """
CREATE TABLE staff(id varchar(11) PRIMARY KEY,
username varchar(20),
password varchar(50)
);
"""
try:
cursor.execute(sql)
print("staff table created successfully")
conn.commit()
except Exception as e:
conn.rollback()
else:
conn.commit()
# 创立员工
@app.get("/create/staff")
def create_staff(id: str, username: str, password: str):
idsql = """SELECT * FROM staff where id = %s"""
idparams = (id,)
cursor.execute(idsql, idparams)
conn.commit()
rows = cursor.fetchall()
if rows:
return -1
else:
sql = """INSERT INTO staff (id, username, password) VALUES (%(id)s,%(username)s, %(password)s)"""
params = {'id': id, 'username': username, 'password': password}
try:
cursor.execute(sql, params)
conn.commit()
except Exception as e:
conn.rollback()
else:
conn.commit()
# 删除员工
@app.get("/delete/staff")
def delete_staff(id: str):
sql = """delete from staff where id = %s"""
params = (id,)
try:
cursor.execute(sql, params)
conn.commit()
except Exception as e:
conn.rollback()
else:
conn.commit()
# 查找所有员工
@app.get("/searchall/staff")
def search_all_staff():
sql = """SELECT * FROM staff;"""
try:
cursor.execute(sql)
rows = cursor.fetchall()
conn.commit()
return rows
except Exception as e:
conn.rollback()
else:
conn.commit()
# 敞开数据库连贯
def close_database():
cursor = conn.cursor()
cursor.close()
conn.close()
! 重要!,此时,咱们进来 Dokcer
容器的那条命令就发挥作用了,咱们进入的时候,映射了两个端口给虚拟机,别离是 80
& 8011
。
如果你没有跑 docker run -ti -d -p 80:80 -p 8011:8011 --privileged=true centos:7.8.2003 /usr/sbin/init
这条命令就进入虚拟机,很道歉,你须要回到创立 docker container 的地位从新创立 …
写好 main.py
后,执行以下命令:
uvicorn main:app --host 0.0.0.0 --port 8011 --reload
# 按 ctrl / command + c 可进行运行
此时,你在浏览器的地址栏中输出,你的物理机 IP,前面加上:8011
,就能看到 hello world
的提醒。
IP 后输出 :8011/docs
你还能看到 fastapi
为咱们筹备的 交互式 API 文档,你能够在外面测试连贯数据库是否存在问题。
:8011/docs
还能进行肯定的接口测试,看看返回的 Data 是否合乎本人的须要。
如键入中文值存在问题,请返回到上文,看看是否是,DataBase Encoding
的编码问题。
另外,如果你的 Uvicorn
在后盾运作,而你心愿重新启动,可应用以下命令让它进行运行
# 查看端口被哪个过程占用
netstat -lnp|grep 8011
# 如果无奈应用 netstat 执行:yum install net-tools
# 查看过程的详细信息
ps 11100
# 杀掉过程
kill -9 11100
# 通常,还需再应用 netstat -lnp|grep 8011 复查
更多详细信息:https://blog.csdn.net/u011389…
4. 可能存在的 Psycopg2
操作 PostgreSQL
数据库问题
如果没有 import psycopg2.extras
& cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
这段代码。
你的 /searchall/staff
申请的返回值,就不会以键值对的模式返回给前端。
以下内容你能够疏忽
当初我为了这个问题,“学习了”下 PostgreSQL
json
& jsonb
数据类型的操作,jsonb
的读取性能更快(比 json
快很多很多倍,然而程序会乱)
上面放一下 jsonb
的 数据库命令 操作,即,间接在 sql shell
中执行的命令
# postgresql jsonb 增删改查 知识点记录 📝(留神!是 jsonb):# 在 sql shell 创立表:CREATE table test_jsonb(id int, info jsonb);
# 增:insert into test_jsonb values(2, '{"company":"sanzro design","name":"sanzro","career":"Full Stack Engineer"}');
# 删(临时不晓得如何通过 jsonb 去删除整个元素):delete from test_jsonb where id = 2;
# 改:update test_jsonb set info = info||'{"company":"sanzro design"}' WHERE id = 2;
# 查:select * from test_jsonb where info @> '{"company":"sanzro design"}';
# 查问 id
select * from test_jsonb where id=2;
还有如果你须要 id
自增,则创立表的时候将 id
配置为 serial
:
CREATE TABLE test_jsonb (
id SERIAL PRIMARY KEY,
info jsonb
);
当 id
为自增时,其它不变,插入数据变为:
insert into test_jsonb (info) values('{"company":"sanzro design","name":"sanzro","career":"Full Stack Engineer"}');
其它遇到的问题
后端解密小程序函数
! 重要!,须要 pip install pycryptodome
,上文有提及
如果仍旧无奈应用,请参考此链接🔗:从“正告:请勿应用 pycrypto
”看起:https://qastack.cn/programmin…
# 示例代码
from fastapi.encoders import jsonable_encoder
@app.post('/code')
def user_wxlogin(appid, secret, code):
params = {
'appid': appid,
'secret': secret,
'js_code': code,
'grant_type': 'authorization_code'
}
url = 'https://api.weixin.qq.com/sns/jscode2session'
r = requests.get(url, params=params)
openid = r.json().get('openid', '')
session_key = r.json().get('session_key', '')
return {'openid': openid, 'session_key': session_key}
内容较长,感激 🙏 你看到这里。
如有误,请提出,必纠正,谢谢。