浅谈架构–Less is more哲学的延伸
今天电话面试, 提到优秀架构的特点.
着实让我脑袋空了一把, 这个太难说了. 快速思考了一些之后, 我回答说, 简单.
好的架构并不会有特别复杂, 可以让每个人都看的懂, 这是我心中的好的架构. 但不知道面试官会怎么想. 我要详细说一下为什么这么个回答, 如果说的不对, 拍砖拍死我吧.
道家有云: 大道至简, 建筑大师密斯也说过: Less is more. 简单是好的架构的特点, 受欢迎的语言也是如此.
举个几个栗子:
一. 高并发的web
所有高并发的动态web结构简化后都是以下3大块:
- 存储层
- 控制层
- 请求响应层(apache/cgi/nginx)
于是为了达到高的并发能力
- 各层做好自己的缓存, 尽量不给底层带来压力.
- 各层把本身性能做好.
- 各层把任务发给最合适的下层.
- 存储层
- 如果是数据库, 索引/外键/冗余数据设计好
- 控制好连接数, 慢查询的日志要跟Monitor配合, 快速处理.
- 访问压力大, 解决掉写入瓶颈问题
- 增加存储节点(对读写分离完全不建议, 同步延迟不说, 没必要这么做)
- 控制层
- 访问存储层, 添加redis等内存级缓存, 使用连接池减少连接次数与连接数, 尽量减少查询上下流, 尽量远离join查询, 只update需要update的内容.
- 多存储节点的选择控制(hash与map规则, 或者可以使用中间件的工具)
- 优化处理能力, 可以多线程, 多进程, 协程, 异步, 减少cpu消耗/资源占用/等待时间等.
- 模块分工, 公共library开发 ,library以外的模块没有任何耦合, 让各小队可以独立前进.
- 瓶颈优化, 可以考虑把library与各其他有瓶颈的地方着重优化, 保证快速响应.
- 对于完成业务类型更多的内容, 比如数据层的访问与管理, 可以单独拉出一层.
- 请求响应层
- 加大Request队列容量(针对不同的环境可以考虑Request去重).
- 堵塞快速处理
- 控制请求分发至其他服务器/控制层/静态文件.
- 静态文件CDN存储.
实际上以上的描述是所有高并发网站共有的架构.
以上架构还缺了一个很重要的环节, 就是monitor, 再专门做好monitor, 监控好log,加入报警event, 这个系统就非常完美了.
大部分开发为了让项目更可控, 都会使用MVC把控制层细分, 但我要说的是view可以分拆出去. model层实际上属于私有library. 对求性能的web来说, ORM是累赘, 可以逐步砍掉. 真正需要加大投入的还是在Controller层.
有些框架是MVT, 比如Django, 不管框架怎么细分层, 按产品内容去分任务, 每个人分到不同的任务就可以做不同部分的事情, 同时也可以对特殊产品使用特殊的架构. git版本控制是神器, 合并分支又这么简单, 所以还应该从OOP往流程化收敛一下.
针对web还要提到一些提升性能的问题, 可以在前端靠javascript的访问实现一些动态数据, 比如用户信息, 购物车. 这样跨部门合作, 提升性能都会非常棒的.
二. 爬虫架构
web是流出型服务, 爬虫是流入型业务. 这里就简单些说.
- 下载器(downloader)
- 解析器(parser 可以合并到控制器)
- 存储器(importer)
- 控制器(controller)
- 下载器的能力决定了下载速度, 有些特殊的业务是需要反”反爬虫”技术的, 可能需要加代理, 填写验证码等等.
- 控制器的排重决定了爬取的有效率
- 存储器有必要可以对数据进行简单的清洗
- 有些业务类型比较特殊, 需要专门写解析器, 还要有出错反馈机制.
最大的瓶颈是在下载器, 下载器用异步会大大提高效率, 再搭上多线程或者多进程, 那这个下载器就无敌了, 这样之后的瓶颈有可能会在网络或存储的I/O.
所有程序想要达到更高的执行效率, 就需要有更脱离可读语言的编写, 比如异步twisted, 这些看似复杂, 其实经过好好思考, 原理也是非常简单.
还是要说, 要加上一个Monitor, 监控log, event, 配合工作, 这也算架构的一部分.有些要做unit test, 实际上, 这就是个保险丝的作用.农村家里没有保险盒,很容易一家短路全村断电. 要不要强制做, 要看团队的素质与代码质量和unit test的优先级.
三. 架构中的中间件与控制层
目前有名的框架/软件 都会有个middleware
实际上middleware是一个通用逻辑的处理, 我以上所说的两种架构实现的框架都会加上很多Middleware层.
我还是很喜欢Middleware这种设计的, 但是返回来思考, Middleware 只是被控制的一部分, 属于控制层.
而且在框架中一般都会有个Engine控制middleware, 也同时控制着你写的控制层.
为了架构更有针对性, 控制层就可以细分成为多个不同的控制单元, 下文中将会提到.
大部分人在看到架构图的时候会搞的一头雾水, 实际上就是被这些中间件与引擎搞的, 大家下次再看架构图的时候不妨先把middleware忽略掉, 然后把控制层与引擎合并, 再看看架构是又多简单.
附 Scrapy 架构图 vs 简化架构图:
存储器
控制器 — 下载器 — Internet
解析器
架构进阶:
通过以上的描述, 其实我们已经得到了最精良的骨架.
架构师接下来还是要根据产品的访问量与本身业务特点细化, 尤其是控制层的地方. 比如web控制层可以分为mvc, 然后在各层加上中间件, 可以按project/app/的结构来实现不同产品或项目的管理, 使每个产品与项目有自己都有的settings与middleware.
下一步应该是各个不同的业务类型中的实现, 比如有的需要消息服务, 队列服务, 特殊的存储, 连接池子等等.
最后用简洁的图表达出来, 如上图scrapy的架构图.
至于UML图就让大家一起参与进来吧, 因为这些都是血肉了, 等画图来和写出代码来也离的没多远了.
总结:
有本书叫«架构之美», 架构是一门艺术也是哲学, 不仅仅在程序上, 在国家企业管理上一样得以体现, 好的企业或者国家的管理都简单有效.
圣经旧约中曾提到, 以色列在管理人的时候要分很多层级, 而层级的领导人只管理10个人左右. 当下互联网盛行, 也兴起了扁平化的管理.
对于管理学, 设计管理方式的工作就叫做架构. 每个伟大的管理方式, 不管是扁平化管理还是层级管理, 都极其经典并且简单.
我是建筑学出身, 看过一大些好的设计. 国际著名的建筑大师做出的作品, 都可以用一张极其简单的草图画出来, 比如大家熟知的鸟巢, 央视大楼, 东直门的当代MOMA, 三里屯的Soho. 简单背后你能看到的是专注与专业.
软家架构也应当如此, Less is more.