自 3.0 以来,Bali框架已经相对完善,具有HTTP / RPC / EVENT功能,3.2 版本是一个优化1.0,2.0,3.0所有功能细节的版本。从3.2开始,希望更多的Python团队在转换微服务或转换云原生时可以享受到 Bali 的好处。
涉及的变化是非常大的,Github 的 3.2 版本发布记录说明。
虽然变化多变化大,但是没有不兼容的更新。所以的新功能及优化都兼容早期版本。
让我们来详解一下几个比较大的变化点吧:
-
Model 新增 manager 概念
相信 Django 是很多 Pythonista 的入门框架,Django 的 Model 里面的文档 advanced 部分有关于 manager 的介绍,https://docs.djangoproject.com/en/4.0/topics/db/managers/。Bali 3.2 引入的 manager 概念与 Django 里面的 manager 概念非常相似,只不过调用方式不同。
<pre># Sync
user = User.io.first()
Async
user = await User.aio.first()</pre>
-
Model 新增优雅的异步 API 方案
近些年大部分的语言都拥有了完善的异步 IO 方案,从早期的 JavaScript 里面的 defer、 promise,到 Java 里面的 Netty,Go 里面的 Goroutine。不管哪个方案,都没有 Python 里面这么纠结的就是同步和异步是同时需要提供的。像 JavaScript 的 promise,内置的网络请求返回的总是 promise 对象,你只能用异步 IO 的思维去处理。
还未发布的 Django 4.1 已经在 Model 层增加了异步方法,API 如下:
<pre>Person.objects.acreate(first_name="Bruce", last_name="Springsteen")
Person.objects.afirst(first_name="Bruce", last_name="Springsteen")</pre>
可以看到,Django 的 QuerySet 及 Manager 对异步的支持是在原有的单词上增加了 a
,个人觉得这样让代码可读性及语义化受到了干扰,create 一眼就知道是创建的意思,acreate
是什么,如果我熟悉 Django,我会猜到这是异步的调用方式,是一个 awatable 的函数。如果业务里面需要自定义一个函数呢,比如 choose_best,这时按 Django 的方案就是 achoose_best 表示异步 IO 的方式。可以看出,choose 并不像 get、create 这么常见的时候,achoose 让我们产生了疑问,单词拼写错误?看 PyCharm 已经用波浪线提示拼写错误了。
Bali 里采用的 API 方案是 Query 使用 io/aio 来区分同步和异步,而对于 Model,自动根据当前的上下文来自适应,看一下使用示例:
使用 Manager 时
<pre># sync
user = User.io.create(username=username)
async
user = await User.aio.create(username=username)</pre>
使用 Model 的实例时
异步示例:
<pre>async with db.async_session() as session:
result = await session.execute(
select(User).where(User.username == username)
)
user = result.scalars().first()
由于 user 是在 async_session 的 context 里面查询出来的
所以 user 的自带的实例方法(save, delete 等)都自动转换成了异步方法
await user.save() </pre>
同步示例:
<pre>user = User(username=username)
user.save()</pre>
-
简化的注册 Resource 的方式
3.2 版本引入了 Resource 的注册使用方式,为了配合这个方式,Bali 将 Application 进行了大量重构及优化。这样一来,main.py 启动入口的代码得到了极大程度的精简。我们看一下对比:
之前版本需要将 HTTP 服务的 routers 及 RPC 服务的 service 分别传入,3.2 的版本只需要指定 title 及注册 Resource 就可以了。对应的 routers 及 service 会在启动时自动去动态生成。
我们再来看一下 Resource 转成 HTTP 服务的方式变化:
之前需要手动在 urls.py 里面手动注册,3.2 将 resource 注册到 app 后,路由相关的文件全部可以移除,是一个可选项。当然旧项目升级时,完全不受影响,因为原来的方案也注册的方式兼容,同时使用原来的定义方案及注册的方式也是可以正常的。
-
gRPC 的服务文件的极度简化
为什么说是极度简化呢,因为原来的 gRPC 的文件 services/rpc/service.py 这个文件直接可以移除了。
-
gRPC 的服务文件的极度简化
项目结构 layout structure 的变化对比:
除了 core、logic、biz 等概念,services 也从固定的结构被成了灵活结构,关键是整个 services 都是可选的。如果所有的业务都使用 Resource 开发,将没有 services 文件夹。