Mean全栈架构


编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由桑世龙在高可用架构群分享。转载请注明来自高可用架构公众号「 ArchNotes 」。

桑世龙,天津空弦科技 CTO,开源项目 Moajs 作者,Node.js 技术传道者。曾就职在新浪、网秦,曾做过前端、后端、数据分析、移动端负责人、做过首席架构师、技术总监,全栈技术实践者。目前主要关注技术架构和团队梯队建设方向。

“JavaScript 是世界上使用最广泛的语言,没有之一,包括后端开发工程师也更爱使用 JavaScript。”  ——stackoverflow

http://stackoverflow.com/research/developer-survey-2016 )

后端分布

( http://stackoverflow.com/research/developer-survey-2016 )

Node.js 与生俱来的 2 个特性:

  • event-driven
  • non-blocking I/O

以前总强调的异步特性,到今天异步已经不是明显优势。因此除了性能,其他都是病(不足)?

1、Callback hell 问题

目前已经很好的解决了。promise / generator / async 后面会讲。

2、包管理

npm 已经是开源世界里最大的包管理器了,模块非常丰富(25.6万 )。

Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

以前我们总是喜欢拿异步说事儿,现在我们拿 Node.js 的强大的生态来炫耀。

https://github.com/nodejs/nan )自己包装 C/C++ 轮子

从上面看,绝大部分需求都可以满足了 

2、如果语言层面搞不定,那就架构层面做

  • 业务边界、模块拆分、面向服务
  • MQ、RPC、cache
  • 运维、监控、自动化

稍微解释一下,首先,架构与 Node.js 没直接关系。其次,架构师常用的东东有足够的 Node.js 模块支持,比如 MQ,像 Rabbitmq 有比较好的 Node 模块支持,RPC 里 Thrift、Grpc、Tchannel 支持的都不错,我们使用的 senecajs,Redis,ioredis 等软件,后面做 HA 都是一样的。

3、如果架构层面也解决不了……

合适的场景用合适的东西。有很多东西是 Node.js 不擅长,又不在架构范畴里的,咋办?如实在不够,Java 补(严格点,应该叫其他语言补)

  • 比如复杂 excel 生成
  • 比如 apns 推送(Go 做其实也很好,不过除了我,没人能维护)

但凡是 Java 或其他语言里比较成熟的库,可以作为独立服务使用的,都可以做 Node.js 的支持。避免过多的时间用在造轮子上,影响开发进度。

4、Node.js 优劣分析

  • 执行效率,同样不优化,性能比大部分语言好。
  • 开发效率,Node.js 本身比较简单,开发效率还是比较高的。完善的生态,比如测试、工具、npm 大量模块。
  • 缺少 Rails 一样的大杀器,scaffold 脚手架,ORM 太弱。

Node.js 的 Web 开发框架 Express、Koa 等,简单,小巧,精致,缺点是集成度不够,目前已有的 MEAN 或 yo 或 sails 等总有某种方面的不满意

MongoDB 2015回顾:全新里程碑式的WiredTiger存储引擎 )。
  • Angular 的出现是一个时代,IoC,双向绑定,指令等都曾让无数热血沸腾。
  • Node.js 提供了完全的生态和工具链,你要的它基本都有,感谢 npm,早些年 Node.js 的性能甩 php 几条街的。
  • Express 作为 Node.js 示范项目,它非常精简,是比较合适的 Web 框架
  • 我为什么选择 MEAN 架构?

    • 成熟、稳定,简单,有问题我们能 cover 住,所以我们选了 Node.js。
    • 把握趋势,以后 Node.js 的前景非常看好,尤其前后端统一,全栈方向。
    • 在架构上可以屏蔽可能风险,不孤注一掷,也不会一叶障目,合理的使用其他语言,只要每个功能都以服务出现,至于它是什么语言写的,并不重要。
    • 招人成本的性价比相对较高,技术栈新,容易吸引人才。

    最重要的一件事儿,是当有问题的时候,有人能 cover 住,在创业初期这是最最重要的事儿。

    Node.js最新Web技术栈https://cnodejs.org/topic/55651bf07d4c64752effb4b1

    https://cnodejs.org/topic/560dbc826a1ed28204a1e7de

    http://developer.github.com/v3/ (严格的restful) 

    微博 API (可读性强,相对比较传统),我们采用的微博 API 类似的,约定结构也是类似的。

    res.api is an express middleware for render json api , it convention over api format like this :{     data : {},    status: {        code : x,        msg : "some message"    }}
    客户端 API 开发总结https://cnodejs.org/topic/552b3b9382388cec50cf6d95

    约定结构

    和 Java 开发里的目录结构类似,该分层的分层,适当的按照 Express/Koa 增加中间件、路由等目录,便于开发。

    使用 npm 模块化

    • 使用 npmjs 的 private 私有模块(目前做法)
    • 使用 npm 的本地模块开发方法(测试和部署都非常快)
    • 搭建 npm 私服(todo)

    编写生成器

    在 Web 开发里,写了 Moajs 生成器,类似于 rails

    moag order name:string password:string

    其他开发,如 iOS 开发里模型校验非常烦,于是写了一个 json2objc 命令行工具,读取 json,生成 oc 代码,可以节省不少时间

    Moajs 框架和前后端分离

    • 前端 (moa-frontend   https://github.com/moajs/moa-frontend )
    • public下面的采用 Nginx 做反向代理
    • 其他的采用 Express Jade 精简代码(ajax与后端交互)
    • 后端(moa-api https://github.com/moajs/moa-api )

    moa 生成器,即上面讲的生成器 scaffold。

    moa-frontend 技术栈:Express / Jade / bootstrap、bootstrap-table / jQuery / gulp / Nginx

    moa-api 技术栈:

    • base2(mirco kernel)   https://github.com/base-n/base2-core
    • mongoose   https://github.com/Automattic/mongoose
    • bluebird   https://github.com/petkaantonov/bluebird
    • res.api  https://github.com/moajs/res.api

    Features

    • 自动加载路由,自带用户管理,使用 jsonwebtoken 做用户鉴权
    • 支持 MongoDB 配置,集成 mongoosedao,快速写 CRUD 等 dao 接口
    • 支持 migrate 测试,Mocha 测试
    • 默认集成 res.api,便于写接口
    • 集成 supervisor,代码变动,自动重载,gulp 自动监控文件变动,跑测试
    • gulp routes 生成路由说明
    • 使用 log4js 记录日志

    从开发效果上看,还是非常快的,非常稳定的。

    Moajs框架演进之路https://cnodejs.org/topic/567e2388aacb6923221de469

    NW.js )
  • Electron  - Build cross platform desktop apps with web technologies
  • 目前比较火的编辑器都是基于 Electron 打包:

    • Atom
    •  vscode

    组件化:统一用法

    React 的出现影响最大的是 JSX 的出现,解决了长久以来组件化的问题:

    • 我们反复的折腾 JavaScript ,依然无法搞定
    • 我们尝试 OO,比如 extjs
    • 我们最终还是找个中间格式 JSX

    单纯的 React 只是 view 层面的,还不足以应用,于是又有 Redux。核心概念:Actions、Reducers 和 Store,简单点说就是状态控制,然后再结合打包加壳,变成 app 或可执行文件。iOS、Android 上用 Cordova,PC 上使用 Electron。

    总结

    • 组件定义好(React)
    • 控制好组件之间的状态切换(Redux)
    • 打包或加壳(Cordova or Electron)

    这部分其实组件化了前端,那么能否用这样的思想来组件化移动端呢?

    react-nativehttps://github.com/facebook/react-native)A framework for building native apps with React. http://facebook.github.io/react-native/

    简单点说,就是用 React 的语法来组件化 iOS 或 Android SDK。它们都在告诉我们,你们以后就玩这些组件就好了,你不需要知道复杂的 SDK 是什么。

    当下流行玩法

    Medis is a beautiful, easy-to-use Redis management application built on the modern web with Electron, React, and Redux. It’s powered by many awesome Node.js modules, especially ioredis and ssh2. https://github.com/luin/medis

    技术点

    • 使用 Node.js 模块
    • 使用 Webpack 构建
    • 使用 React(视图) Redux(控制逻辑)
    • 使用 Electron 加壳打包

    亲,你看到未来了么?

    Moa FrontEnd  就是最简单前后端分离,里面没有任何和 DB 相关。

    技术栈

    • Express
    • Jade
    • bootstrap,bootstrap-table
    • jQuery
    • gulp
    • Nginx

    一般的前端都非常容易学会,基本 2 周就已经非常熟练了,我的计划是半年后,让他们接触【异步流程处理】和【数据库】相关内容,学习后端代码,就可以全栈了

    3、从移动端转

    移动端分:native 原生开发,hybrid 混搭式开发。原生开发就是 iOS 用 oc/swift,Android 用 Java 或 Scala 等,就算偶尔嵌入 webview,能玩 JavaScript 的机会也非常好少。所以移动端转全栈的方法,最好是从 cordova(以前叫 phonegap)开始做 hybrid开发。只要关注 www 目录里的 H5 即可,比较简单。如果 H5 不足以完成的情况下,可以编写 cordova 插件,即通过插件让 JavaScript 调用原生s dk 里功能。cordova 的 cli 可以通过 npm 安装,学习 npm 的好方法,学习 gulp 构建工具。

    只要入了 H5 的坑,其实就非常好办了。

    • 然后 H5、Zeptojs、iScroll、fastclick 等
    • 然后微信常用的,如weui、vux(vue weui)、jmui(react weui)
    • 然后可以玩点框架,比如 jQuery mobile,Sencha touch
    • 然后可以玩点高级货,ionicframework(基于Angularjs、cordova)
    • 然后前端 4 阶段,依次打怪升级
    • 然后 Node.js

    这个基本上是我走的路,从 2010 年写 IOS、做 phonegap(当时是0.9.3)一路走到现在的总结吧。

    http://i5ting.github.io/history-of-node-js/ )

    Node.Js 为什么会成为企业中的首选技术? )

    2015年 IBM (收购 StrongLoop,拓展云服务业务)

    Node.js 基金会的创始成员包括 Joyent、IBM、Paypal、微软、Fidelity 和 Linux 基金会。

    对于企业级开发,Node.js 是足够的,无论从性能、安全、稳定性等都是非常棒的。

    空弦科技做的是基于云仓储的 SaaS 服务,给中小卖家提供服务,核心系统是进销存、订单池、WMS。目前来看不存在任何问题

    es && babel

    2015 年 ECMA 国际大会宣布正式批准 ECMA-262 第 6 版,亦即 ECMAScript 2015(曾用名:ECMAScript 6、ES6)的语言规范。

    babel (http://babeljs.io/)作为 es 编译器,已经大量开始使用了,模块做的非常棒,还有人用babel写其他语言编译器。Node.js 里在 0.12 之后才增加 es6 特性,es7 的目前还不支持。所以在 Node.js 里使用 es 里比较高级的特性,是需要 babel 去编译处理的。这是 Node 追逐的标准。

    2016 年 01 月 22 日,(微软请求 Node.js 支持 ChakraCore https://github.com/nodejs/node/pull/4765 )

    未来 Node.js 不只是基于 chrome v8 内核,它还可以支持更多其他浏览器内核,对生态、效率提升等非常有好处。

    蔡伟小兄弟的查克拉 benchmark 的对比( https://github.com/DavidCai1993/ES6-benchmark )基本结论是 V8 ES5 > 查克拉 ES6 > 查克拉 ES5 > V8 ES6

    https://github.com/typicode/json-server/ ),负责是后端开发的 leader 在写,他的进度会比正常开发要早一周左右。目前不是一个人写所有的前后端,团队成立不久,天津 Node.js 会的不多,所以还是前后端分离。但是通过 moa-frontend 可以让前端了解 Express 等后端知识,适当的时候会给予机会,前端转后端。

    3. 贵司在开发协作中提到了静态 API,请问是不是有什么比较好的工具可以推荐?

    桑世龙:Node.js 里(json-server https://github.com/typicode/json-server ) 比较好

    我其实很想围绕静态 API,写各种请求的生成器,只要 API 出来,文档和各平台的 HTTP 请求代码就生成出来,同时可以对正式 API 进行压测,可惜目前还没精力写。

    4. 做 hybrid app 在移动端会遇到性能问题吧,有没有什么优化经验可以分享?

    桑世龙:足够轻量级,少选大框架,做好前端该有的优化。注意 touch 和 click 的区别,比如 fastclick 或 Zeptojs 的 tap 手势。Chrome profile(css3动画)。使用 weinre 真机测试。参考:(我的  H5实践 。

    5. 如果都全栈了,当前你们团队是如何分工的?

    桑世龙:我们团队还是倾向于分工专业化,各个服务粒度非常小,便于轮岗、还有就是可以为以后像 Google 那样代码开放做准备。但是有很多情况下,是需要有机动的突击队的(尤其是创业时期),这样可以随便组合,另外就是全栈为 remote 提供了更多便利性。

    6. H5 在手机上用 iScroll 坑比较多啊 尤其三星打开硬件加速的时候 render 页面,桑老师怎么看?

    桑世龙:可以尝试一下淘宝系的 H5 虚拟化,鬼道曾经在 as 大会上讲过的,我们目前还没能力做这么深层次的优化。

    7. Node.js 做业务金额计算的金额性能和精度够吗

    桑世龙:你问的不是 Node.js,而是 Node.js 要操作的数据库。耗性能的计算可以在架构上平衡的,如果可以延时,MQ 就可以了。如果是非延时情况,可以采用其他语言编写对应服务,没必要非要一定要 Node.js。我们目前的场景,还没有在计算遇到瓶颈。

    8. 关于 API 返回格式那里,对于 status 为什么不打平了把 code 和 message 放出来?这么设定有什么好处么?

    桑世龙:语义上更加清晰。整个返回的 json 就只有 data 和 status,如果 status.code != 0,我取 msg 就好了,如果等于 0,处理 data 数据这种设计不见得多好,不过结构清晰,对于开发者来说,是比较容易接受的。

    本文策划李庆丰,编辑王杰,审校 Tim Yang

    原文地址:http://weibo.com/ttarticle/p/show?id=2309403956502426692050