Tornado 如何组织中大型项目,你们都是怎么样做的?

2015-11-26 22:24:16 +08:00
 mywaiting
用了 tornado 也写网站,无它,当初就是因为喜欢,因为 tornado 的代码写得真心漂亮。

一开始我是这样组织项目的,你没有看错,真心只有这几个文件:

+ project
| - app.py (基本所有的 handler 都在这里了)
| - models.py (数据库相关的)
| + templates
| + static

如果要给个参考例子,那 BT 大大的项目来参考吧 https://github.com/finiteloop/socialcookbook 刚刚开始写 tornado 的项目的时候没有那么多的东西,一切都很简洁很美好!

然后呢,项目越来越多功能了,需要组织的代码越来越多,需要 Seesion ,需要 form 检验等一堆东西,于是重构为这样来组织项目:

+ project
| + controllers
| | - acontroller.py
| | - bcontroller.py
| | ....
| + models
| | - amodel.py
| | - bmodel.py
| | ....
| + templates
| + forms
| | - aform.py
| | - bform.py
| | ....
| + helpers
| | - ahelper.py
| | - bhelper.py
| | ....
| - application.py
| - urls.py
| - settings.py

很直接也很明显,这是拿 Tornado 来做 MVC 这龌龊的事情了,把先前越来越大的 app.py 分开成 controllers 目录, models 目录页一样,增加了 forms 目录和 helpers 目录。 application.py 放置整个 project 的启动、关闭, URL 放在 urls.py , settings 嘛就是配置。

这样安好运行了好长一段时间,毕竟一个小网站,长成这样已经很对得起我拿的工资了。但是这样的项目结构随着业务的增多感觉越来越力不从心:

1 、首先业务关联比较多,类似于门户网站那样的 CMS 类型的,这样就无法分出几个项目来应用上面的代码组织了。
2 、子域名的需求众多,基本一个子域名 a.example.comb.example.com 的代码逻辑是完全不一样的,但是数据库后面的数据却有很多需求重合的。同时原因见 1 ,又无法分出好几个 project 来组织代码

感觉越来越臃肿的代码结构,越来越多的东西加入到 Tornado 这个大杂烩里面,感觉项目长得越来越像 Django 的项目,但是组织却远不如 Django 的项目组织得好!

看了一下 Flask 的 Blueprint ,这货貌似在架构大型项目的时候很实用的样子。

就像这篇文章 https://spacewander.github.io/explore-flask-zh/7-blueprints.html 说到的按照功能(functional)或者分区(divisional)来组织代码。

按照 分区(divisional) 来组织代码貌似有天生的适合大型的且内部可以松耦合的项目,而类似我上面的 按照功能(functional) 来组织项目就适合组织功能相对内聚的项目。

按照我这么重构下去,迟早要弄个 Django 出来的感觉。有点后悔当初怎么不直接用 Django 而用上了 Tornado 来自己造各种轮子。

各位在架构 Tornado 的中大型项目,有什么经验可以分享吗?

谢谢!
12128 次点击
所在节点    Tornado
23 条回复
janxin
2015-11-26 23:13:28 +08:00
本质上蓝图组织方式 tornado 里也能用,只不过是需要拆分就好了。至于蓝图的 url 组织形式, tornado 里也有人实现过了 url 修饰器功能,修改一下就可以用了。

模型复用比较多的时候,我的项目组织比较类似,不过 controller 部分进行了模块拆分。

其实我也觉得 django 挺好的,除了性能…
mywaiting
2015-11-26 23:27:16 +08:00
@janxin 跑在 Gunicorn 中,有 Gevent 、 Eventlet 的加持,不会差很多吧
janxin
2015-11-26 23:30:29 +08:00
@mywaiting 提升有,但是还是会有性能影响
zhuangzhuang1988
2015-11-26 23:31:26 +08:00
大型项目? 没做过. 不过看过 ipython notebook 中的代码的
https://github.com/ipython/ipython/blob/3.x/IPython/html/notebookapp.py#L223
mywaiting
2015-11-26 23:36:23 +08:00
@zhuangzhuang1988 没有想到 IPython 里面也有这个,冏....

谢谢了~
fwee
2015-11-26 23:42:12 +08:00
我也是最近刚用,不是按照 MVC ,而是按照功能模块放在不同的 package 里,然后多拆分 handler
wingyiu
2015-11-26 23:43:32 +08:00
不一定要在同一个项目吧?比如那个不同子域名的。拆分成不同的小 tornado 项目 单独部署不也是一种方式吗?重复的部分搞成一个库咯?
mywaiting
2015-11-26 23:53:11 +08:00
@wingyiu 主要拆分成小的 project ,那会很小啊,懒得拆了再开多一个 git 仓库了。其实 django 或者 flask 那样类似 package 组织的话,可以组织得挺好的 :)
slixurd
2015-11-27 00:47:41 +08:00
RPC 啊 SOA 啊
好吧,我受 Java 荼毒太深。
zeayes
2015-11-27 08:47:15 +08:00
拆分一下项目吧,做下服务化,是明智的选择。
tuteng
2015-11-27 09:15:53 +08:00
同感
yueyoum
2015-11-27 10:08:02 +08:00
python web 生态圈 为何 Django 一家独大?

因为其他框架 做到后面, 基本都是你自己添加各种东西,拼凑出一个 Django 来
但是 远没有 Django 本身优雅
janxin
2015-11-27 10:53:56 +08:00
@yueyoum Django 到现在都不支持 MongoDB 这个让我挺遗憾的...
mywaiting
2015-11-27 11:07:29 +08:00
@yueyoum 基本都是这样的吧,因为 web 开发都是这些东西,要是用 tornado 、 flask 这样的,那就只能不断去拼凑了,最后都差不多整成 django 这样或者近似 django 等大型框架这样。

但是不能否认,这么拼凑的过程中,自己不断造轮子可以对 web 开发的理解深刻好多。回头再来用 django ,那就基本是稍微翻翻文档的事情吧。
lianghui
2015-11-27 11:18:39 +08:00
把最近的 tornado 项目分层结构参考 分享下。 吸收了 scala 框架与一些其他语言框架的特性, 使用了 tow scope 的概念,使用了 hocon 配置,使其可被文件配置。


https://github.com/whiteclover/Zephyr


/CODE/ZEPHY
│ requirement.txt
setup.py
│ zephyrd

├─conf
│ app.conf # hocon 配置
├─schema
│ mysql
└─zephyr
app.py # 应用
autoload.py # 自动加载容器
breeze.py #核心容器实现
cmd.py
feed.py
flash.py
helper.py
jinja2t.py
log.py
options.py
orm.py
patch.py
pedis.py
session.py
util.py
__init__.py

├─asset #静态文件
│ ├─js
│ └─theme
│ └─default
│ ├─css
│ ├─img
│ └─js
├─boot # 命令控制
asset.py
database.py
jinja2t.py
pedis.py
site.py
__init__.py

├─config # 配置加载 lexer 类
errors.py
hocon.py
_config.py
__init__.py

├─lang
│ │ __init__.py
│ ├─en_GB
│ ├─zh_CN
│ └─zh_TW

├─lib
image.py
memoize.py
paginator.py
validator.py
__init__.py

├─module # 模块 api 分割
│ │ __init__.py
│ │
│ ├─category
│ ├─comment
│ ├─extend
│ │ │ mapper.py # orm 层
│ │ │ model.py # 领域类, 可以进一步分成模块文件夹
│ │ │ thing.py # 逻辑层
│ │ │ __init__.py
│ │ │
│ │ └─view # url 控制与 url 路由
│ │ field.py
│ │ __init__.py
│ │
│ ├─front
│ │ mixin.py
│ │ view.py
│ │ __init__.py
│ │
│ ├─menu
│ │ thing.py
│ │ view.py
│ │ __init__.py
│ └─user
mapper.py
model.py
thing.py
view.py
__init__.py

└─template
├─admin
│ ├─extend
│ │ ├─field
│ │ ├─metadata
│ │ └─plugin
│ ├─layout
│ │ edit.html
│ │ footer.html
│ │ header.html
├─component
│ views.html #组件
└─theme
└─default
felixzhu
2015-11-27 11:39:14 +08:00
其实都是这样的,慢慢的到最后就会做成 Django 。。

楼主可以参考下网上的开源项目的结构,比方说 sentry 之类的,然后自己拓展一下
waytwoex
2015-11-27 12:35:45 +08:00
受到 php 的荼毒,我这个架构其实也不怎么样。。仅供参考……
https://github.com/phith0n/Minos
northisland
2015-11-27 20:11:17 +08:00
@lianghui 请问这图是怎么生成的?
shajiquan
2015-11-27 20:25:27 +08:00
@northisland 这不是文字么。用 tree 命令就生成了。
northisland
2015-11-28 11:05:59 +08:00
@shajiquan 刚装上 tree ,多谢了~

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

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

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

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

© 2021 V2EX