XWeb 基于 Python 语言 高性能异步 Web 框架

发布于 2020-08-02 14:20:26 字数 4426 浏览 1684 评论 0

XWeb 框架是一款基于 Python 语言的 Web 开发框架。

特点

  • 框架使用了高性能的 uvloop+httptools.
  • 框架全部采用 python3.6 后的异步 async await 语法.
  • 框架架构参考了 koa.js。
  • 高性能
  • 插件式
  • 全异步

为什么使用 Python?

我曾经使用过Java、PHP、Ruby和Python来开发Web应用,至于为什么使用Python作为XWEB的语言,其实最主要的原因:

  1. Ruby不再需要新的WEB开发框架,Rails统治了一切。
  2. PHP没有多线程,对于后台数据处理有些吃力。
  3. Java其实非常好,但不是脚本,仅此而已。

开发这个框架的目的

  1. 现有框架如Django, SQLAlchemy无法解决实际开发过程的一些问题,如全局唯一ID,短事务,N+1等。
  2. 现有框架如Django, SQLAlchemy设计地过于复杂,各种坑爹配置,没有统一的标准,让使用者无从下手或者无法精通。

特性

  1. 一个轻量级的MVC框架和ORM框架
  2. 采用工作单元来组织数据模型,提供级联查询,延时加载,N+1=>1+1,短事务,全局唯一ID和Identity Map等特性,能有效防止数据库死锁的发生。
  3. ConnectionManager管理工作单元内的数据库链接,支持跨库提交,跨库事务等。

主要思想

马丁福勒的《企业应用架构模式》一书

原则

主要原则

  1. 只有一种配置,就是最佳配置。 拿ID来说,有些业务实体的ID是没有含义,有时候仅仅是为了让INNODB更有效率,如: user_friend_ref表,有三个字段:id,user_id,friend_id,没有人会关心id字段 对于主键有意义的业务实体,统一使用全局唯一ID,如:
user = User.createByBiz()
order = Order.createByBiz()
order.user_id = user.id

如果使用Django的ORM,要写出: user = User() user.save() order = Order() order.user_id = user.id order.save()

  1. 数据的读写

从cache和从库中取出的数据是不允许写入主库

设计思想

本框架有一个ORM框架和一个MVC框架构成,其主要设计思想如下:

  1. 每个域名一个App,启动单独的uwsgi,如需要泛域名、静态化等需求,请在nginx层处理。
  2. 一组App组成一个站点,其共用领域实体类,Service等,但是有各自的controllers和templates,如:www、admin等。目录结构如下:
     /domain         - 领域文件夹
         /entity         - 领域实体类
         /object         - 非领域实体类
         /service        - 领域服务类
     /www            - www子App
         /controller     - 控制器类
         /templates      - 模板文件夹
         /static			- 静态文件
     /admin          - admin子App
         /controller
         /templates
     /config         - 配置文件目录
    
  3. App只负责业务逻辑和展示页面,数据库操作、基本的缓存等由框架负责处理,一般情况下,程序员不需要关心。

设计原则

  1. 脚本即配置,且配置文件全局唯一
  2. 约定优于配置,一切不涉及旧系统迁移的规则一律不再设置配置选项,例如:模板存放, action标识码等
  3. 基于MVC架构,抛弃MVT模式,业务逻辑依托类来组织
  4. 数据库链接、Cache链接等全部采用LazyLoad模式加载,由ConnectionManager和CacheManager统一管理,不提供预加载,减少分库时链接
  5. 从代码组织上讲,分库优于分表,因此不提供分表功能,请大家尽量采用分库来代替分表
  6. 轻量级,可运行于console程序
  7. 数据库表名含义明确,全局唯一,例如:admindb中的user表表示管理员用户,而wwwdb中的user表表示注册用户,是不允许的,至少加上前缀,如admin_user
  8. 类名全局唯一,虽然Python提倡module的概念,也有支持package命名空间,但是类名重复对业务代码组织及维护有百害而无一,坚决杜绝这种设计

名词解释

App: 以域名划分,例如,一个项目有前台,后台,图片等服务,分别为www.xxx.com, admin.xxx.com和img.xxx.com,则分别对应www,admin和img的app

Controller: 以业务需求划分,例如:用户相关操作,订单操作分别属于UserController和OrderController,需要登录的在Controller的基类中实现或者在before方法中实现

Action: 一次具体的请求,如:下单,可标示为: controller/action,此为默认地址,rewrite规则书写方式为: c=controller&a=action。

Hello World

from xweb import App

app = App()

@app.use
async def response(ctx):
    ctx.res.body = "Hello World"

if __name__ == '__main__':
    app.listen(8000)

koa.js 官方例子 xweb 版

import time
from xweb import App

app = App()

@app.use
async def logger(ctx, fn):
    await fn()
    rt = ctx['X-Response-Time']
    print(rt)

@app.use
async def response_time(ctx, fn):
    start = time.time()
    await fn()
    usage = (time.time() - start) * 1000_000
    ctx['X-Response-Time'] = f'{usage:.0f}µs'

@app.use
async def response(ctx):
    ctx.res.body = "Hello World"

if __name__ == '__main__':
    app.listen(8000)

性能

  • 测试代码目录,为了公平,所有服务都启 4 个进程进行对。benchmarks/
  • 环境: iMac (Retina 4K, 21.5-inch, 2017), 3 GHz Intel Core i5, 8 GB 2400 MHz DDR4
  • 压测命令: wrk http://127.0.0.1:8000/ -c 100 -t 10 -d 10 -T 10

Requests/Sec:

  • xweb 90000
  • vibora 90000
  • meinheld + wsgi 77000
  • sanic 50000

相关链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

漫雪独思

文章 0 评论 0

垂暮老矣

文章 0 评论 0

鹊巢

文章 0 评论 0

萌酱

文章 0 评论 0

雨说

文章 0 评论 0

冰葑

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文