想要使用 FastAPI 重构项目,应该如何快速入门?

2021-01-29 21:34:18 +08:00
 LeeReamond

大家好,我有一个 Python web 项目需要在近期重构。

对我来说我的需求主要有两点,其一是我需要后端有较高的可用性,所以我必须要使用异步特性,其二是由于我与后端数据库交互中有很多涉及高级特性的操作,并不适合使用 ORM,大多数情况下需要直接写 SQL 。所以这几天在论坛里收集信息之后决定使用 FastAPI 这个框架。

我原先的项目是使用 aiohttp 构建的,基本上属于毛坯房中的毛坯房,涉及到参数读取、权限、数据库操作等各方面都需要自行配置。因为在同步时代也是使用 flask,这方面倒是没有给我造成太多困扰。根据以往的经验,项目中通常要配置大段的业务代码实现对输入参数的可靠读取,以及发生错误时返回完善的异常信息,而 fastapi 在这方面的自动化确实是很吸引人。

我在粗略通读 fastapi 的文档后,觉得还是需要来 v2 问一下使用过的大佬的经验,以免走弯路。再加上本着学习一门新工具的态度,我觉得还是要先问一下,不适合直接把以前的做法往上面套。

===============

我目前的问题是以下几点:

1 、我需要开发一个 SPA 网页项目,即引擎需要进行 html/js/css 的服务,同时使用 API,而不单纯是一个 API 接口,这似乎与这个框架的设计初衷不符,所以产生了两个问题。

其一是在文件服务的部分,我在粗读文档的过程中没有找到比较完善的项目模块化配置信息,也就是各种静态文件应该如何妥善安排结构、模板,并妥善地提供服务等等,我想知道 fastapi 是不是不适合做这方面的操作,有没有过去使用中遇到坑的朋友。

其二是在接口方面,fastapi 有完善的支持,并且能自动生成文档,但其中一些特性是我不需要的。举例来说,自动文档功能不是我所需要的,在大多数时候我不想暴露接口的详细信息,只需要在错误时返回可供 debug 的异常信息即可,对于如何关闭文档功能这方面,我在粗读 fastapi 文档时没有找到太多信息。

2 、关于权限系统,在接口的参数读取方面,fastapi 的文档中的说明令人欣喜,可以让我摆脱大段的业务代码维护可靠读取和可靠异常返回,但是关于权限我并未在文档中获取到太多信息。我目前的项目有一套依赖于 jwt 的权限认证,我想知道 fastapi 在这方面有没有集成,比如像 django 那样的有一套完善权限解决方案,还是我仍需要像以前一样自己实现一套权限系统。

3 、FastAPI 完全支持 OpenAPI, 但是我个人对这个标准不是十分熟悉,我想知道使用,或者不使用 openapi 这套规范是否会对我的项目产生什么影响?

4 、后端服务的连接方面有一些问题,如上文所述我需要在项目中直接连接关系型数据库,以及 redis 缓存服务器,在以往的框架使用经验中我需要自行配置这些客户端。但是由于 fastapi 同时需要使用另一个我没接触过的引擎 uvicorn 进行服务,我不太了解这个引擎的规则,例如通常我们在一个业务节点中(比如单台服务器)通常 prefork 出多个监听进程来利用 CPU 的多核心,我想知道 fastapi 里通用的配置规范是什么,哪些代码在 fork 前执行,哪些代码在 fork 之后,因为涉及交互,以及 logging 相关的操作,我希望节点能最大限度地公用连接。

比如 log 操作当中,多节点共同对一个文件写入日志,单纯写入并没有什么问题,但遇到日志过长,需要滚动的情况,fastapi 应该如何处理,让 logging 系统可以正常地清空不需要的内容?

5 、我目前的需求是,尽快地将项目的模块化配置好,然后实现一套完整的路由映射、权限管理、之后能让我比较快地进入到业务代码的开发(如同使用所有其他项目一样),由于业务代码逻辑复杂且繁重,工期还需要尽量快,这也是我使用 python 作为开发语言的原因,我想问一下有没有什么网上有的比较好的教学可以帮助我。

谢谢大家。

7321 次点击
所在节点    Python
39 条回复
yexiaoxing
2021-01-29 21:47:57 +08:00
静态文件可以用 nginx/apache 来 serve 吧,不需要靠框架。其他的可以看一下 fastapi 自己带的实例,里面实现的东西不少。
LeeReamond
2021-01-29 21:52:05 +08:00
@yexiaoxing 我想让开发和部署更简化一些,如果全部服务由业务节点提供,nginx 只进行转发的话,我对项目的掌控力度更强,部署上也简单一些,静态性能方面我觉得异步时代倒是不需要做特别担心。例子方面,文档中有完整的路由+权限的例子吗,我没有找到
gjquoiai
2021-01-29 21:54:45 +08:00
建议别上 asyncio,可用性和异步没啥关系吧?
LeeReamond
2021-01-29 22:00:24 +08:00
@gjquoiai 那应该用什么呢? django 对于我来说有些过于重了,性能也不太达标,虽然实际生产部署以后用户数量未必能达到 django 的转发能力上限,但是还是留有余地的好吧,我觉得这种需要大量通信的业务 asyncio 在延迟和转发效率上都挺有优势的。
gjquoiai
2021-01-29 22:13:09 +08:00
@LeeReamond #4
生态太差。。第三方库趟不完的坑。。甚至标准库也。。_(:з)∠)_
so1n
2021-01-29 22:18:32 +08:00
你说了这些,既然不需要文档之类的,starlette 就够用了,排查问题方便,没 fastapi 恶心。
权限系统在 github 搜索有很多开源的,哪个顺手用哪个。
mysql 非 orm 的只有 aiomysql 可以用,在 start_event 启动和 stop_event 关闭,具体 fastapi 文档有给出
日志的话用 linux 的 logroate 就够用了,而且没坑,安全。
wdhwg001
2021-01-29 22:27:11 +08:00
aiohttp 到 fastapi 的重构没啥意义的,除非你原本代码真的稀烂到一点功能都加不进去了。
不然你还是去用 gin 一类的 go 框架重构吧。
abersheeran
2021-01-29 22:37:59 +08:00
首先~aiohttp 性能比 fastapi 好,别听它那个宣传词,fastapi 别说跟 go 比了,比 bottle 这个古老的 WSGI 都慢。aiohttp 迁移到 fastapi 意义不大。
其次,如果你不需要文档功能,就像楼上说的,直接用 starlette 更好,因为 fastapi 就是把 starlette 和 pydantic 拼起来了,pydantic 提供了文档功能。日后如果你要从 starlette 升级到 fastapi 也很容易。
另外,看你说的技术栈似乎在同步里积累的更多?那么不如试试 bottle,这个比 flask 还古老的框架。速度比任何异步框架都快(也比 django/flask 快),而且一切都是你熟悉的那一套。只是出于性能考虑而换框架的话,可以考虑试试这个。

最后,说一句题外话:“无脑劝人上 Python asyncio,应该天打雷劈”
abersheeran
2021-01-29 22:39:18 +08:00
Python 异步不仅仅只有不成熟的 asyncio,还有很成熟的 gevent 。
LeeReamond
2021-01-29 22:40:26 +08:00
@so1n
@wdhwg001
原来项目倒不是稀烂,因为性能需要要把 cpu 密集的部分用 cython 重写,想干脆把接口全重构一下算了,aiohttp 到 fastapi 确实不是太大的变动,选这个框架主要还是因为近期比较火,感觉以后也会一直是生态领头的工具,所以想学起来,像 starlette 这种主要还是用的人少,能不能完美满足需求倒是其次,项目不用大众化框架搭感觉没有钱途。切换 go 框架则是步子太大了,py 的业务生态要换到 go 怕是今年都做不完了
LeeReamond
2021-01-29 22:43:19 +08:00
@abersheeran 前几天专门发了一个帖子测试,gunicorn+uvloop+aiohttp 的性能确实是没有 gunicorn+uvicorn+fastapi 的好,不过这个倒不重要,qps 也就是四万比五万这种感觉,需求是一种普遍性的快,而不是要快到极致,高出的性能完全冗余了。
gitopen
2021-01-29 22:43:28 +08:00
看来楼主已经想好了。🐶
LeeReamond
2021-01-29 22:44:48 +08:00
@so1n
@abersheeran
starlette 我不太了解,他在多大程度上和 fastapi 耦合呢?比如我需要的参数注入,starlette 使用上和 fastapi 完全相同?
abersheeran
2021-01-29 22:47:27 +08:00
@LeeReamond 严重怀疑你的测试有问题。https://github.com/the-benchmarker/web-frameworks

另外,你怎么测到四万的? Index.py 都只能跑三万,这两就更别提了。
zhuangzhuang1988
2021-01-29 22:48:39 +08:00
直接用 go 重写呗..
LeeReamond
2021-01-29 22:50:10 +08:00
@abersheeran prefork 模型,不是单进程,不 fork 的话在生产中没有太大意义。详细可以参考,https://github.com/TechEmpower/FrameworkBenchmarks
LeeReamond
2021-01-29 23:07:17 +08:00
@zhuangzhuang1988 有很多 py 依赖不能很容易的迁移,比如项目中一些科学计算的部分依赖 numpy 和 pandas,可视化方面 html 前端可以用 echarts 解决,图片就只能依赖 matplotlib 了,另外还有一些中文自然语言处理的内容,这些都迁移到 go 我头都要大了。还有有时要进行一些信息爬取,这个 go 应该也能做,但是还是 py 更熟悉一些,写得快
so1n
2021-01-29 23:10:32 +08:00
@LeeReamond starlette 需要自己实现参数注入 简单来说,fastapi 基于 starlette+pydantic 框架
abersheeran
2021-01-29 23:30:26 +08:00
@LeeReamond 啊这……prefork 只是分叉出多个进程,对于大部分 Python Web 框架来说,可处理量的增长是线性的。
LeeReamond
2021-01-30 00:06:14 +08:00
@abersheeran 显然不是线性的,实际测试中我用 gunicorn 启动的几乎所有框架都存在软上限,比如单进程 qps 可以达到 15k,四进程并不能达到 15k * 4,实际大概会达到 15k*4*0.5 这样,广义的说比如你有一台 64 核心的机器显然用 fastapi\aiohttp\index.py 这种也不能做到单机百万并发

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/749706

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX