在使用异步框架时,最重要的问题就是保持异步。这一点十分影响我们对于框架组件的选择,如不能用 requests 只能用 aiohttp,不能用 pymysql 要用 aiomysql。那这里就有一个问题了,对于模板引擎 jinja2 我们是否需要替换?下面我用 aiohttp-jinja2 来说明一下。

aiohttp-jinja2 和 jinja2

通常在异步框架中处处是异步,因此会认为 aiohttp-jinja2 是 jinja2 的异步修改版本,如同 aiomysql 和 aiopg 一般。但事实并非如此,查看源码会发现,aiohttp-jinja2 仅仅在模板路由方面适配了一下 aiohttp,此外仅仅加了一层包装,使其可以作为协程装饰器。

为什么不将 jinja2 改为异步版本呢?在寻找答案的过程中有了一个意外发现,jinja2 从 2.9 版本开始添加了异步支持,这一点在官方文档也已经指出,我们完全可以直接使用 jinja2 作为异步模板而不需要任何修改。但在 aiohttp-jinja2 的源码中并没有开启异步功能,这又是为什么?

异步 jinja2

因为事实并非这么美好,aiohttp-jinja2 的开发者们在发现 jinja2 支持异步功能时,第一时间就进行了讨论和测试,结果是令人失望的,引用 samuelcolvin测试数据:

Requests/sec:
    enable_async=False                    594.52
    enable_async=True                     219.19

可以发现 jinja2 开启异步模式后,在 aiohttp 框架中的性能反而下降了,不足在同步模式下的 50%。这里的性能下降在官方文档就已经说明,只不过没想到下降了这么多。在 jinja2 没有做出重大修改之前,为了异步而开启 jinja2 的异步模式可以说是得不偿失的。

总结

协程是为了解决异步 io 问题,以前一直纠结 jinja2 这类的模板程序是计算阻塞型还是 io 阻塞型,现在看来应该是计算阻塞型。jinja2 本身已经够快,以后直接使用即可,不用过多担心异步阻塞,当然 aiohttp-jinja2 作为包装过的 jinja2,更适合配合 aiohttp 框架使用。