Node.js Server之二:业务框架
发布于 6 年前 作者 Shasharoman 3252 次浏览 来自 分享

Node.js Server之二:业务框架

此文是自己正在使用的Node.js Server分享系列中的第二篇,继上一次的Node.js Server之一:概述后,本文讲述自己对业务框架的理解和自己的实践总结。

业务框架是什么

想不到一个更好的标准名词来总结自己与大家分享的这部分内容,综合考虑内容的核心是业务与框架,因而称之为业务框架。

上篇文章提到Express、Koa、Egg,我称之为基础技术框架,它们偏向于提供基础的API与技术概念供大家使用,而使用它们提供的API结合具体业务所组成的中间层框架我称之为业务框架。在Express、Koa、Egg这三个框架中,Egg相对特别,我认为它不是一个技术框架,而更偏向于是一个业务框架,正如其官方口号“为企业级框架和应用而生”,这是最好的例证。

在一个具体的项目中,指导实现某个功能所需要的通常步骤以及如何完成这些步骤的约束,再加上对实现该功能所能提供的帮助,这三者共同构成一个业务框架的基础。简而言之,业务框架是不同公司,不同技术组,实现不同业务需求的一种经验体现,由于公司不同,技术人员不同,业务需求不同,业务框架在细微处可能千差万别,但业务需求通常存在共性,这就是Egg的价值。

为什么需要业务框架

解释过业务框架是什么之后,再聊聊为什么需要业务框架。

我们都知道有编码规范,命名规范等,业务框架可借此作类比,它是你实现业务功能方式的约束与规范,通过约束和规范,业务框架能给业务实现提供指导,同时尽可能的减少重复工作。

业务框架的难点在于不同公司的业务差异,同一个业务框架,A公司觉得非常好用,到了B公司变成另外一个评价,这是有极有可能的。也正是因为不同公司之间的差异导致公司与业务框架匹配度不尽相同,我们才需要自己的业务框架,并结合业务进行持续优化。

实践

在实现自己的业务框架时,一个好的开始是至关重要的,我们不是从零实现一个HTTP Server,只是为了更好的与业务结合,可选择基于Express或Koa。

因为做的事情与Egg类似,不建议使用它作为业务框架的基础,但可以学习Egg的原理,然后应用到自己的业务框架上

核心要素:

  • 配置

用配置描述行为,用程序解释配置,主要包含基础配置与单个App配置

  • App

业务边界的体现,小的话像一个模块,大的话更像一个应用,统一称为App

  • AppManage

管理App,如初始化App,提供App间通信

  • bootstrap

实例化AppManage并启动

以上四个点是自己业务框架的主心骨,下面描述每个要素的核心内容。

配置

配置描述行为,程序解释配置,业务框架便是这个程序,基础配置文件主要包含以下信息:

  • 应用基础信息,如:name、host、port等
  • app路径、middleware路径、静态资源路径等
  • 需要启动的app列表
  • 全局中间件申明
  • 应用所需其他配置

所有业务框架需需要知道的信息都可以通过配置指定,然后业务框架会根据host、port启动server、根据app路径查找要启动的app列表项配置,根据中间件申明挂载相应中间件…

通过定义配置加载规则和其背后的行为,你几乎可以实现自己的所有想法,但也有可能搞的一团糟,这也是乐趣的来源。

分享一个配置大家感受下:

// alpha.json
{
    "name": "alpha",
    "env": "prod",
    "host": "127.0.0.1",
    "port": "8001",
    "path": "/Users/shasha/private/isl",
    "appPath": "/Users/shasha/private/isl/app",
    "fwPath": "/Users/shasha/private/server",
    "modules": [
        "common",
        "wechat",
        "view",
        "alpha"
    ],
    "component": {
        "converters": [
            "entity",
            "cookie",
            "session",
            "clientIp"
        ],
        "redirectors": [],
        "interceptors": [{
            "mode": "dev",
            "name": "asset.file",
            "options": {
                "dir": "asset"
            }
        }],
        "interferes": [],
        "finishers": ["log.access"]
    },
    "lib": {
        "mysql": {
            "database": "alpha"
        },
        "redis": {}
    },
    "oss": {},
    "session": {
        "redis": {}
    }
}

大部分内容大家都能理解,但对于component中的内容可能一下看不明白,其实也就是中间件,只不过是用自己定义的规则和加载方式体现罢了。

App

在概述那篇文章中,我提到过分层和分模块的顺序问题,我觉得先分模块再分层更合理,这里App的概念便是模块,对应基础配置中modules的每一项。

App表示一个应用/模块,其主要内容包括:

  • 根据模块配置进行实例化
  • 对外提供init、start、restart、reload、stop等生命周期方法
  • 在start中根据配置进行路由注册、中间件注册
  • 按配置对外暴露必要接口,用于模块间通信

App可通过Class定义,实例化时传入模块配置,服务运行阶段该实例可一直被AppManage持有用于控制某些模块行为。

AppManage

AppManage作用相对简单,就是集中管理App,主要在应用启动阶段读取App配置、实例化App,在服务运行阶段对外提供App间通信接口。

bootstrap

有了配置、App以及AppMange之后,我们需要启动整个server,主要使用命令:node server/index.js -c xxx.json,下面描述一下命令背后的主要过程:

  • 解析配置文件xxx.json

解析命令行参数,按路径读取配置文件并做必要转换与解析,比如将同一配置内容的不同表达方式转换为统一形式

  • 通过Express或Koa实例化一个HTTP Server

为中间件申明、路由注册、端口监听作准备

  • 设置Server全局行为

主要是一些全局中间件,如Cookie、Session、Body-Parse、AccessLog等,这部分行为尽量也按照配置文件内容进行设置

  • 实例化AppMange

根据配置文件的内容实例化AppManage,在AppManage内部会实例化所指定的App,并持有引用

  • 调用AppManage的init方法

顺序或并发调用所持有App的init方法,这个阶段主要是让每个App内部做一些准备工作,比如建表,注册定时任务等

  • 调用AppManage的start方法

调用持有App的start方法,App-start需要作的事情主要是依照模块配置注册路由与中间件,这中间的具体规则与实现都是灵活的,可简单可复杂

  • 代理AppMange的部分方法

部分App内也许会用到一些框架层面的功能,而server不希望对外暴露AppManage,那么AppManage提供的的模块间调用功能就可以通过server进行代理,达到隐藏内部细节的目的

  • 通过前面的Express或Koa实例化的HTTP Server监听host与port

以上所有的步骤完成后,通过所持有的HTTP Server完成监听,整个服务即完整启动了,同时server可以监听部分进程信号,结合AppManage实现reload等功能

总结

这片文章本打算细致的讲解自己server中的所实现的业务框架,但写完后发现还是非常概念化,感觉很多细节都没能展开,计划在下一篇用实战的方式实现一个简单的业务框架。

博客原文

3 回复

对于nodejs,express和koa本身具备了日常开发所需的功能,我自己还是喜欢以乐高玩具的方式自己组装,不喜欢使用egg这类封装好的框架

@yuedun 我也在玩乐高,哈哈~

@yuedun 不一样, express和koa 解耦程度不够, 比如声明式事务? 业务层的剥离?

回到顶部