【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)

教程说明

本教程利用Python异步编程方法,基于FastAPI和uvicorn库来快速搭建并运行网站后台。由于教程偏向于入门,所以我将介绍网站完整建立过程,并对每个可能的疑惑点进行详细解释;如果你已经有自己的服务器,并且掌握SSH和FTP的连接方法,可以直接跳转至第三步。

文章预览:

      • 教程说明
      • 一、准备工作
        • 1.申请云服务器
        • 2.申请自己的域名
      • 二、配置Xshell和Xftp
      • 三、服务器环境配置
        • 1.创建Python虚拟环境(可选)
        • 2.fastapi和uvicorn的安装
      • 三、开始编写网站后台
      • 四、为服务器配置Nginx代理
      • 五、网站连通性测试
      • 后记——为server.py添加中间件
      • 完整代码


一、准备工作

  • 一个有公网IP的服务器
  • 一个域名(可选)
  • SSH终端: Xshell
  • 文件传输: Xftp

1.申请云服务器

根据业务需求的不同, 当然也可以选择租用国外vps,比如:

  • 亚马逊:AWS云服务
  • 微软: 云计算 Azure

​ 可能要绑定visa银行卡且收费较高,不过有免费试用额度, 访问外网资源速度很快;

当然也可选择国内云服务器,比如:

  • 腾讯云:弹性云服务器-腾讯云
  • 阿里云:云服务器ECS-阿里云

​ 注意: 国内服务器和域名都需要进行备案

由于作者刚好有阿里云的学生优惠, 在申请页面按照官方的引导进行身份认证, 于是拿到了一个月免费的服务器;

请注意:服务器的系统镜像请选择发行版Linux,比如Ubuntu、CentOS、Debian等,本教程服务器是阿里云的系统 (应该是从CentOS魔改来的)

2.申请自己的域名

由于阿里云学生申请域名首年一块钱,秉持白嫖到底的态度 我也申请了一个,暂且称为:mydomain.top

【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第1张图片

​ 在下单界面需要创建你的信息模版, 认证身份并进行备案,按照官方流程即可。

3.域名解析

当你创建好域名后,前往你的 域名控制台

在域名列表中,你会看到刚刚申请好的域名,此时点击 “解析” —> “新手引导” :

【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第2张图片
【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第3张图片
继续填写域名解析设置:

  • 您的业务需求:

    这里是根据服务器公网IP来确定的,一般都是xxx.xxx.xxx.xxx格式,即IPv4地址;这里我们选择"解析到IPv4地址"就好;

  • 请选择网站域名:

    如果选择设置@主机记录,则通过http://mydomain.top就能访问我们的网站;

    如果选择设置WWW主机记录,则通过http://www.mydomain.top才能访问网站;

    注: 设置成WWW的好处是便于我们后续添加子域名, 比如api.mydomain.top; 这里我们选择WWW记录

  • 请输入网站IP:

    填入之前创建的服务器实例的公网IP就好了

解析设置成功后, 我们可以在cmd中ping一下我们的域名:

ping www.mydomain.top

如果像图中一样能够Ping得通, 就代表我们配置成功了!

【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第4张图片


二、配置Xshell和Xftp

[Xshell和Xftp](家庭/学校免费 - NetSarang Website (xshell.com)) 这两个软件功能强大、简单易用,且都有家庭和学生免费许可证,比较适合本教程的使用。

Xshell功能: 通过SSH连接我们服务器的终端, 并执行相关命令
这里点击 “连接” 后,会提示你输入用户名和密码,这里根据你的云服务器的系统账号(一般是root) 和密码, 对应输入即可;出现SSH密钥确认界面时点击保存。
【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第5张图片

Xftp功能: 用于本地与远程服务器之间的文件传输, 可以直接复制粘贴文件
(这里填写的信息也与Xshell中一致
【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第6张图片


三、服务器环境配置

到这里为止, 我们已经成功申请了云服务器和域名, 配置好了Xshell与Xftp, 那么接下来开始配置我们的服务器环境。

查看系统python版本:

python --version

本教程使用的Python版本为3.9, 建议Python版本为3.7+

1.创建Python虚拟环境(可选)

教程所使用的FastAPI模块使用了很多Python3.7+的特性,而由于笔者的服务器自带Python3.6版本太低,直接重装可能影响其他系统程序正常工作,故准备建立一个miniconda的虚拟环境。

前往 miniconda主页 查看命令行安装方式:
【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第7张图片

接下来按照官方指引,在Xshell中依此执行下面命令:

# 在root/下新建"miniconda3"目录
mkdir -p ~/miniconda3

# 获取最新miniconda安装包
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh

# 执行安装
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
# 删除安装包
rm -rf ~/miniconda3/miniconda.sh

等待终端完成miniconda的安装后, 执行下面命令初始化conda:

~/miniconda3/bin/conda init bash

接下来创建虚拟环境并命名为myenv, 同时安装Python3.9:

conda create --name myenv python=3.9

等待环境创建完毕, 我们启动这个虚拟环境:

conda activate myenv

此时我们的用户名前缀变成了"(myenv)", 这就代表虚拟环境启动成功了! 这个环境是独立于系统的Python环境的,我们可以在这个环境下安装所需的fastapi和uvicorn模块。

2.fastapi和uvicorn的安装
# 用conda安装
conda install fastapi
conda install uvicorn
# 或者pip安装
pip install fastapi
pip install uvicorn

三、开始编写网站后台

  1. 我们在系统根目录/ 新建一个 mysite 目录, 用于存放我们的网站文件:
   mkdir /mysite
  1. 在你自己的电脑里, 新建一个文件"server.py", 这将作为网站的后台 放在/mysite目录下;

  2. 使用Vscode等代码编辑器打开"server.py"并导入我们需要用到的库,比如数据存储的json、异步操作的asyncio 和处理客户端请求的fastapi,以及运行ASGI应用程序的uvicorn:

   #encoding=utf-8
   import json
   import asyncio
   import uvicorn
   from fastapi import FastAPI, Request
   from fastapi.responses import JSONResponse
   app = FastAPI()	

提示:

  • ASGI: 是一种异步 Web 服务器和应用程序之间通信的标准接口, fastapi和uvicorn都是基于此标准的模块;
  • app: 我们用fastapi实际上是构建了一个ASGI 应用程序, 并将其部署在uvicorn上运行;

​ 注: 考虑到实际开发中网站需要能处理并发的请求, 故我们将采用异步的方式编写后台程序。

  1. 编写处理”GET“请求的函数
   # 处理GET请求
   @app.get("/")
   async def read_root():
   # 读取本目录下的"data.json"文件,将内容返回给客户端
       with open("./data.json", "r", encoding="utf-8") as f:
           data = json.load(f)
       return data

提示:

  • @app.get("/"):是一个Python中的修饰器, 用于捕获对server.py所在路径的GET请求;换言之,read_root()这个函数就与路径 /mysite 绑定在一起了,任何GET请求都会经过这个函数的处理。在这里我们简单实现了一个读取服务器资源并返回给客户端的方法。
  • async: 是python的关键词, 标识read_root是一个异步方法。
  1. 编写处理“POST”请求的函数

    这里简单实现了一个json文件上传功能。

   # 处理POST请求
   @app.post("/")
   async def save_data(data: dict):
   # 将客户端发送的内容存储到本目录下,并向客户端发送一条消息
       with open("./data.json", "w", encoding="utf-8") as f:
           json.dump(data, f)
       return {"message": "Data received and saved successfully"}

​ 注: Fastapi支持的请求方法不只GET和POST, 还有PUT,DELETE等, 实现原理相似, 这里就不给出具体方法了。

  1. 最后添加程序入口,并设置监听服务器本地的8000端口:

    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0", port=8000)
    
  2. 到这一步,我们的网站后台就写好了, 只需用Xftp将server.py上传至服务器的/mysite目录下即可:

【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第8张图片


四、为服务器配置Nginx代理

我们知道:http协议走80端口,而https走443端口,但我们的网站后台只监听8000端口;为了将其他端口的请求转发到8000端口上, 我们还需要配置Nginx进行反向代理

  1. 安装nginx
   # Ubuntu
   sudo apt update
   sudo apt install nginx
   # CentOS
   sudo yum update
   sudo yum install nginx
   
   #验证是否安装成功
   nginx -v
  1. 使用文本编辑器如vim,打开/etc/nginx/nginx.conf:
   sudo vim /etc/nginx/nginx.conf
  1. 找到文件内的server块, 并添加location/字段,完成后如下:

    server {
        listen 80;
        listen [::]:80;
        server_name _;
        root /usr/share/nginx/html;
    
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
    
        error_page 404 /404.html;
        location = /40x.html {
        }
    
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
        
        location / {
            proxy_pass http://localhost:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    
    • proxy_pass 选项用于转发请求至本地的8000端口, 要与我们在server.py中填写的端口一致;

    注意: 点击键盘的"Insert键才能开始编辑文件;完成后点"ESC"键退出编辑模式,然后按":“键输入"wq”,回车后保存并退出文件。

  2. 回到终端界面, 我们来启动nginx :

   # 测试 Nginx 配置是否有误
   sudo nginx -t
   # 启动nginx服务
   sudo systemctl start nginx
  1. 最关键的一步——在终端使用uvicorn启动我们的网站后台,设置监听8000端口:
   # 切换到/mysite路径下
   cd /mysite
   # 启动网站后台
   uvicorn server:app --host 0.0.0.0 --port 8000
这里的`server:app`其实就是代指我们在`server.py`内定义的`app`程序。

当出现下图时就代表网站后台成功启动了 !

uvicorn开启成功


五、网站连通性测试

  1. 我们在自己电脑新建一个"client.py",导入requests库进行测试:
   #encoding=utf-8
   import requests
   
   data = {"message":"success"}
   url = "http://www.mydomain.top"
   
   # 向网站发送一个POST请求
   r = requests.post(url,data) 
   print(r.json())
   # 输出: {"message": "Data received and saved successfully"}
   
   # 向网站发送一个GET请求
   r = requests.get(url)
   print(r.json())
   # 输出: {"message":"success"}
  1. 在浏览器地址栏填入"http://www.mydomain.top",检查是否能打开;

    注意: 如果在国内服务器上搭建了网站, 还需要进行ICP备案

    在服务器端会记录到我们刚刚请求的消息,若出现200 OK字样就代表客户端访问成功了! !
    成功连通


后记——为server.py添加中间件

其实到这里,我们的所有工作都差不多完成了。不过我突然想到, 要是在某段时间内出现大量异常请求怎么办呢? 为了保证网站正常运行, 我决定为server.py添加新功能——增加一个预处理请求的中间件,对IP在一段时间内的访问次数进行限制

思路:用异步方法实现一个非阻塞计时器,并在达到阈值时对已保存的IP字典进行清除

代码如下:

app = FastAPI()
# 记录IP访问次数的字典
ip_access_count = {}
# 异步任务,用于定期重置IP访问次数
async def reset_ip_access_count():
    while True:
        await asyncio.sleep(3600)  # 设置每小时清除一次
        ip_access_count.clear()
        
# 启动重置IP访问次数的异步任务,添加一个协程
asyncio.create_task(reset_ip_access_count())

# 处理IP限制中间件
@app.middleware("http")
async def ip_limit_middleware(request: Request, call_next):
    client_ip = request.client.host  # 获取请求IP
    # 在IP字典中将该IP访问次数+1
    ip_access_count[client_ip] = ip_access_count.get(client_ip, 0) + 1
    if ip_access_count[client_ip] > 100:  # 当该IP请求次数大于设定阈值时返回403
            return JSONResponse(status_code=403, content={"msg": "Access denied for this IP"})
    response = await call_next(request)  # 将请求交给后面处理(这是Fastapi内置方法)
    return response

【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)_第9张图片
可以看到我们的拦截是有效的 !


完整代码

import json
import asyncio
import uvicorn
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()
# 记录IP访问次数的字典
ip_access_count = {}

# 异步任务,用于定期重置IP访问次数
async def reset_ip_access_count():
    while True:
        await asyncio.sleep(10)
        ip_access_count.clear()

# 启动重置IP访问次数的异步任务
asyncio.create_task(reset_ip_access_count())

# 处理IP限制中间件
@app.middleware("http")
async def ip_limit_middleware(request: Request, call_next):
    client_ip = request.client.host  # 获取请求IP
    # 在IP字典中将该IP访问次数+1
    ip_access_count[client_ip] = ip_access_count.get(client_ip, 0) + 1
    if ip_access_count[client_ip] > 100:  # 当该IP请求次数大于设定阈值时返回403
            return JSONResponse(status_code=403, content={"msg": "Access denied for this IP"})
    response = await call_next(request)  # 将请求交给后面处理(这是Fastapi内置方法)
    return response

# 处理GET请求
@app.get("/")
async def read_root():
    with open("./data.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    return data

# 处理POST请求
@app.post("/")
async def save_data(data: dict):
    with open("./data.json", "w", encoding="utf-8") as f:
        json.dump(data, f)
    return {"message": "Data received and saved successfully"}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

阅读至此, 若有不解或有错之处, 欢迎大家留言喔 !

你可能感兴趣的:(FastAPI搭建网站,python,fastapi,开发语言)