1.1 JavaScript言语的演进进程(本图作者justjavac)
1.2 node.js的原理及本质
-
Node.js 不是 JavaScript 运用,不是编程言语(JavaScr( { }ipt 是编程言语),不是像 Rails(依据 Ruby)、Laravel(依据 PHP)或 Django(A a q K依据 PyM k f L M d lthon)相同的结构,也不是像 Nginx 相同的 Web 服务器。NK L ) 4 $ 3 I Iode.js 是 JavaScript 的运转时环境;
-
Node.js 构建f D | + | ` &在 Chrome V8这个闻名的 JavaScript 引擎之上,Chrome V8 引擎是经过 C 或 C++ 编写的z O Q x Q,相当于要将 JavaScript 转化为底层的 C 或 C++ 代码后再履行,经过 JavaScrN y & $ 6 ript 这层包装,大大降低了) C : h n y偏底层的编程言语的学习本钱,Node.js 内置 Chrome V8 引擎,所以运用的是 JavaScript 语法;【Google 发布的开源 JavaScript 引擎,选用 C/C++ 编写,在 Google 的 Chrome 浏览器中被运用。Chrome V8 引擎能够独立运转,也能够嵌入 C/C++ 运用程序中被履行】
-
Node.js 是轻量且高效的,每个函数都是同步的,而 I/O 操作是异步的。一切由 JavaScript 编写的函数的 I/O 操作最终都将由 libuv(由 C/C++ 编e E B z写)事情循环处理库来处理,隐藏了非堵塞 I/O 的详细细节,简化了并发编程模@ c ` O c { #型,能够轻松{ 1 $ % q (编I G S写高功能的 Web 运用;【JavaScript 言语的一大特色就是单线程,即同一时刻只能做一件事。单线程就意味着一切的使命都需求排队,前一个使命结束才会履行后一个使命。假如前一个使命耗时很长,后一个使命就不得不一向等待,一般状况下,排队的时分 CPU 是闲着的。其实 CPU 完全能够不论 I/O 设备而直接挂起处于等待中的使命,先运转排在后边的使命,将等待中的 I/O 使命放到事情循环中,事情循环由 libuv 供给,事情循环负责将文件 I/O 使命放到线程池中,线程池由 libuv 供给。网络 I/O 使命不经过线程池完结, 只需有 CPU 资源,就应尽力履行】
-
node.js 其实就是帮咱们构建了类排队叫号的机制。写代码的进程实际上就是取号的进程,由事J F : P情循环来接受处理,而真正X { { 6履行操作的是详细的线程池中的 I/O 使命。之所l [ 6 M .以说 Node.js 是单线程的,是由于它在接受使命的时分是单线程的,无须切换进程/线程,十分高效,但它在履行详细使命的时分是多线程的。个人了解:事情环中的代码单线程履行,线程池中8 ? U O b v + Y的异步; D b U T I l使命多线程履行
-
Node.js Bindings 层做的事就是将 Chh = 1 r S orome V8 引擎露出的 C/C++ 接口转化成 JavaScript API,而且结合这些 API 编写 Node.js 标准库,一切这些 API[ # U & u , e G p 被统称为 Node.js SDK
1.3 node.js的特色
-
适宜构建web运用
- 构建传Z J q统网站(类似于php、java等将视图烘托和数据拜访放在同一个项目中且前后端不别离的单体式运用)
- 构建API (为h5、ios及android等多客户端供给可复用api,关于用 Node.js 完结 API 接口开发,在技能选型上,无论是挑选通用型的 Express、Koa 结构,仍是挑选专门为 API 开发编写的 Restify、Hapi 结构,都是极端简略的。一些大型工程的 API 相对杂乱,因此在后端的 API 接口开发上封装一层专门供前端y O : R运用的 API Proxy 对错常有必要的。后端 API 接口开发用于数据库拜访,将回来的数据进行包裹,以 HTTP 方法回来;API Proxy 针对前端运用的 API[ H R L n . K l Q 进行优化,使前端开发更人性化)
-
构建RPC服务 (RemoteQ 6 8 Procedure Call,远程进程调用协议服务),常见的做法是将数据库拜访回来的数据,以 TCP 方法传输给调用方* 0 Q B 5 J。相关于 HTTP,RPC 服务选用的是 TCP,Z A = 3 1在协议和传输上有显着优势,Node.js 对错常适宜用于网络运用开发的,其间 SockH ] r D i M n h Cet 编程就是一种典型的网络运t ! l d C 3用开发场景,也就E V / N a q是说,Node.js 相同适宜用于 Socket 编程,运用 Node.js0 ~ i 开发 RPC 服务对错常适宜的。当然,Node.js 完结的 RP: V 7 i TC 服务有很多种,例如朴{ 2 k 1实用 Node.js 完结的 DNode、微服务东西集 Seneca、跨言语的 gR( m 5 P P Y – jPC 客户端,能够看出 Node.js 在微服务架构下的运用场景也对错常多的s & 3 – N * e O [。
- RPC 服务:数据库拜访,将回来的数据进行包裹,以 TCP 方法传输给调用方;
- RPC 拼装服务:拼装多个 RPC 服务,完结某项事务;
- 将 RPC 服务包装成 HT/ a r W & &TP AE Y r # B $ RPI
-
前后端别离 React、Vue、Angular 结构三足大力,关于构建V f d B 8 x大型杂乱网站有必要实施前后端别离
- 前端页面静态化(Page Stati% F ; R % x @ a Sc)
- 前端页面服务化(PAAS,Pag* E Pe as Service)
- 服务端烘托(SSR,Server Side Render)
- 渐进式 Web 运用(PWA,Progresa ; G = C r & gsive Web App)
- 适用于 Serverless 前端范畴演进速度很快,Node.js 的运用场景也越来越多,露出出来的问题自然也十分多,涉及运维、API 快速开发、服务端烘n b L h [ ~ =托等方面,这些问题其实都能够经过 Servn 1 H Jerless 架构来处理。开发者不需求关怀运维、流量处理和容器编列,经R ! n W A K ` ) v过一个函数(内置 RPC、缓存、装备等 API)就能够完结一切开发。能够简略了解为,Serverless 是云核算的延伸,NodX / 2 n u v s 2e.js 在这种运用层开发上有着得天独厚] q R d的优势。有了 Serverless,前端9 % 9无须关怀运维完结,写一个函数就能够搞定 API、服务端烘托等,大幅优化了开发方法,能够想象得到,依托「纯」前端办法完结一切事务也y o E # h I ^是可行的:无须关怀运维(ServI E eerless 渠道自带运维功用,一般a i 2 *集成 Kubernetes 这种容器编列管理u G (体系),无O F q 须关怀. ! ( / W % J Z ;流量(SerC – c # verless 渠道自带服务网格功用,比方 Istio,依据流量能够快速实例化容器),无须关怀高并发(API 层有缓存)。现在,Google 开? & D 7源的 Knative 正在逐渐走向成熟,是一个不错的技能选型。
-
高功能: v W 3 w
- 履行速度快:No7 $ 4 . R z V bde.js 是构建在 Chrome V8 引擎之上的,履行速度或许是动态C P T 5 ] a `言语运转时环境里最快的。
- 天生异步:事情驱动和非堵塞 Iu Z m/O 特性决定了 Node.js 有必要选用异步机制,` _ – u |每个 I/O( _ @ , 8 ( 使命都是异步的,因此集成到 libuv 的事情循环里才干让开发者代码对并发操作无感知。
- 适用于 I/O 密布的网络运用开发:网络运用开发(包括 Web 运用开发)的瓶颈在于 I/O 处理,而这恰恰是 Node.js 的强项。关于 CPU 密布型运用而言,能够运用其他言语开I n )发最好运用其他言语,假如有必要运用 Node.js,能够经过 C/C++Q ` } r h A 扩展机制来完结O f J。由于选用 Node.js 就认为一切功用都要运用 Node.j_ ! 3 , 5s 完结,这是错误的,合理的选用其他技能栈,运用其优势部分,除了能够加速开发迭代的速度,对体系稳定性也对错常有协助的。
-
简略
- 语法简略:JavaScript 语法简略易学,对新手十分友好,关于有前端开发经历或有其他方面 JavaScript 编程经历的开发者而言,愈加简L O W &略。
- 并发编程简略:有了事情驱动和非堵塞 I/O 机制,Node.js 能够运用十分少的资源处理十分多的衔接和使命,处理低延o S ~ + W 1时恳求,完美应对实时及 I/O 密布型运用等高并发场景。
- 布置运维简略:无须运用额外的服务器软件,不像 Java 需求用到 Tomcat 之类* 4 1 q 8的 JavaEE 容器,在分布式集群中,负载均衡、多核体系方面都有完善的配套设施,现有的各种自动化运维东西(如 Ansible、SaltStack 等)都能够直接运用。
- 开发简略:现在 NoB o q y : = –de.js 内置模P 8 ) ` A T Q 块和 npm 上的模块都遵守「小而美」的规划哲学,相对比较简略,对开发0 [ @ a @、迭代、上线有显着协助,不像 Java 里的三大结构包括那么多内容。当然,现在 Spring Boot 也开端9 C k K u % +规划 Java 版别的小而美结构了。
-
可扩展
- 能够运用 npm 上的很多模块。
- 能够经过编写 Ce { 7 K ( . f F/C++ 扩展完结 CPU 密布^ C D ; 2型使命。
- 能够轻松调配 Java、Rust 等言语运用。
- 架构互补:在C a O架构上以事务鸿沟来进行服务拆分,外加各种「组合拳」,能够让适宜的轮子出现在适宜的位置上,比, f j 5方 Java 在根底渠道建设及大数据等范畴有十分深厚的根底,那么直接运用即可。
1.4 node.js的运用场景
- 跨渠道开发:简直g h 7 ? H / 7 – –掩盖你能想到的面向用户的一切渠道,传统的 PC Web 端、移动端、HTML5、React Native、Weex,以及硬件 Ruf} G z ` @ B Z l Of.io 等
- 后端开发:面向网站、API、RPC 服务等。
- 前端开发:三大结构 React、Vue、Angular 辅佐开发及工程化演进进程(运用 Gulp、Webpack 构建 Web 开发东西)。
- 东西开发:主要是开发 npm 上的各种东b ) / z U西模块,包括各种前端预编J Y Q g ;译东西、构建东西 Gulp、脚手s W G h架、指令行东西等。
2.1 3m部分指令
nvm arch 检查当时2 & 6 S 6 R G I体系的位数和当时nodejs的位数w v p
nvm install <verY U V + , : I e ksion> [arch] 装置拟定版别的node 而且能够指定渠道 version 版别号 arch 渠道
nvm list [available]
- nvm list 检查现已装置的版别
- nvm list ins/ P k z | . E Gtallf & I Z * zed 检查现已装置的版别
- n{ ~ 4vm list available 检查网络能7 w R够装置的版别
nvm on 翻开nodejs版别控制
nvm off 关闭nodejs版别控制
nvm proxy [url] 检查和设置署理
nvm node_mirror [url] 设置或许检查setting.txt中的node_mirror,假如不设置的默许是 https://nodejs.org/dist/
nvm npmJ V C 0 ^_mirror [url] 设置或许检查setting.txt中的npm_mirror,假0 M ` 1如不设置的话默许的是:httpsd v c Z + [ ] . c://github.c~ ` f s x Som/npm/npm/) x Z , = v M ( _archive/.
nvm uninstall <version> 卸载拟定的版r R S % ; a A # T别
nvm use [version] [arch] 切换拟定的node版别和位数
nvm root [path] 设置和检查root途径
nvm vej 7 i | ] E 2rsion 检查当时的版别
nvm install v5.0.0 --reinstall-packages-from=4.2 将4.2版别的大局包导入5.0
nrm test 测速
nrm add nam8 c } g T _ Ne url 添加源j p ! h W * + / =
第3章 了不得的node.js
3.1 典型企业选用的3层架构形式
- 体现层 :处理 HTTP 恳求,直接回来 HS A R b * DTML 烘托,或许回来 API 成果。关于一个杂乱的运用体系,体现J – Y层一般是代码中比较重要的部分。
- 事务逻辑层 :完结详细的事务逻! N e辑,是运用的中心组成部分。
- 数据拜访层 :拜访根底数据,例如数据库、缓存和消息行列等。
3.2 Java后端分层
- 先定义模型层(Model)r C H,数据库操作一般选用 ORM 库来简化操作,模型会和数据库里的表进行相关映射。
- DAO(Data Access Object),就是咱们常说的增修正查,主要对单个模型进行操作。
- Service 层就是事务逻辑层,一般组合多个 DAO 对象进行某项事务处理。
- Controller 里拼装了多个 Service 对象,可完结详细的功用。
现在前后端的大致区分图:
3.3 传统和现在分类方法
按照传统分类方法,体现层即前端,而事务逻辑层和数据拜访层都属于后端。现在,最常见的形式是前端 +API+ 后端服务,出于负载均衡、恳求转发、反向署理? l 5 } } | p M、静态资源托管、防跨域等原因,往往需求6 b } G Z d I调配 Nginx 一同运用。* ) @ G ` r
- 方法1:恳求—> Nginx—> 前端 【一般来说,Nginx 是由运{ p ^ . – I 6 F维团队(OPS)负责一致管理的,假如想要改变,就需求走改变申请流程,跨部门合作显得特别费事。但一同,前端又需求处理一些下线、重定向、兼( + & u容多版别等逻辑,处理历史遗留问题,假如每次改变都走改变流程,那开发功率是不可忍受的。既然 Nginx 必不可少,而前端又需求必定h 9 r W t E I的可操作空间,那么是否能够依据这两点找到处理方案呢?最简略最常用的办法,就是在原有方法不变的状况下,在前端引进 Node.js。】
- 方法2:恳求—P / $ l 5 D &> Nginx—> Node.js(前端)【这儿的 Node.y 8 A T f P js 能够完结以下功用。1.供给恳求转发、反向署理等功用;2.供给 Web0 $ % D + z ` j 服务,一切后端言语(Java、PHP 等)能做到的,Node.js 都能做到;3.圈定规模,便于保护,只需修正功用包括在当时 Node.js 项目规模O ! 0 (内即可保护;4.充当 HTTP 客户端,拜访后端接口,但一般不直接拜访数据库】
两种方法的差别如下:
- 方法 1:过度依靠 Nginx,在布置运维和团队合作方面(尤其是跨部门)比较费事。
- 方法 2:运用 Node.js 来代替 Nginx 的 HTTP 功用,让前端有更多的灵活性。
1.8 单体式运用和微服务的对比U a [ W 0 a s { b
3.4 静态API(mock数据)
传统流程:【按照传统的软件工程形式,产品司理提出需求文档(PRD),给出原型图(UE),交给规划师做出高保真的 UI 图,回归到 PRD 中,和前后端开发人员承认后即可排期。整个[ 1 + 2 . # f U流程是一环扣着一环的,在没有完整的 PRD 之前,开发人员什么都做不了,后端不给 API 结构,大前端(App、H5、PC)的开发人员只能切1 Y F v切图。而后端的 API 规划需求 UI/UE,有必要知道功用要做成什么样才干建模,进而给出 API 接口,此进程依靠 UI/f } : { 2 M VUE。规划师也挺「烦」的,产品给出的需求需求证明、考D s U 9 } $ t P (虑、排版、_ Z , / o w ?规划、配色等,重复和产品司理交流是最痛苦的环节,所以规z @ k H , & S划和需求方也是相互依靠的】
改善流程:【在开发流程中选用node加一层静态 API(也能够叫 Mock API),给出模仿的接口,在测试前预留出和正式接口联调的时刻,4 端(App 端、H5 端、PC 端、后端)都并行开发】
3.5 现代的web开发
懒散是p 2 t ; } –人类文明进步的真正动力!
HTML 写烦了,便开端引进模板引擎
CSS 写烦了,便开端引进j 1 6 / y b | CSS 预处理器 SasB l N P 9 +s、Less、Stylus、PostCSe X O O Y T JS 等
JavaScript 写烦了,便开端引5 * + d h : @ s进更友好的言语,比方了解 Ruby 的会运用 CoffeeScript,P ) , 7 z Q了解 Java 和 C#的会运~ t ? – K h d /用 TypeScript
于是乎,进入现代web年代
3.6 web运用(Web 运用大致分两种,带视图的传统 Web 运用和面向 API 接口的运用)
3.6.1 node.js结构特性分类
3.6.2 结构选型准则
考虑事务场景、特色,不用为了用而用,防止舍本求末。
考虑自身团队才能、喜好,* I ^ ! F { @ X有时分技能选型决定团队气氛,需求平衡激进与稳定。
保证在出现问题的时分有人能够做到源码级定制。Node.jsR J q { K 0 现已有 10 年历史,但模块完善程度良莠不齐,假如不小心踩到一个坑里,需求团队在无外力的状况处理问题,否则会影响进度。
3.6.3 node.js部分误解
单线程很软弱,这是F Y c事[ w * _ W v ~实,但能够经过 Cluster 模块完结多核并发处理网络恳求。
运维其实很简略,日志收集、监控也十分简K % C V R B U F略。
在模块稳定性G & 上,Node.js 对 MongoDB、MySQL、Redis 等的支撑仍是相当不错的,但对其他的数据库的支撑或许没那么好。
安全问题是一个伪出题,一切结构面对的安全问题都是相同的。
3.7 API署理
3.7.1 杂乱项目API面对的问题
一个页面的 API 十分多。数据= Z `涣散,前端恳求次数增多
AV E 2 .PI 回来的数据对前端不友好。后端回来的并非前端想要的数据结构,又要开端扯皮
需求决定 API,API 反应不及时。前端过分依靠后端数据,后端大佬不给接口,老子就不写
跨域。
3.K [ U $ 7 f u D [7.2 模型proxy层
将异构的 API(或许是 RESTful API,或许是 RPC 服务)拼装到一同,能够形成供前端运用的合理的新 A| N b M u ] ( @PI,为前端HTTP服务供给更好的API
如图 l # 3所示,图中左边,浏览器和 Node.js 服务通信间能够有多种协议,HTML、RESTful、BigPipe、Comet、Socket 等,足够咱们完结任何想做Y Y m ? ~的事。图中右侧是 Node.js 完结的 WebServer,Node.js 服务分B ~ V z % 3为如下两个部分。
API Proxy 位于异构 API 之前,经过对异构 API 进行抽象,形成模型层,然后依据各种前端需求,包装成对应的 API 接口。最了解前端的只有前端,运用 API Proxy 层能够较好应变,在中间层进行各种转化处理,5 k M / s : 5 e让 API 对前端开发愈加友好。
3.8 服务拼s S @ S R G ` Y装
在微服务架构十分盛行的今日,服务化可谓最佳实践,运用十分多的就是依据 TCP 的 RPC 服务,比较于 HTTP 来说功率更高,再结合装备中心、服务注册等,能够很好地对体系进行解耦。微服务更是在事务鸿沟分拆方面做到了极致,以事务维度来拆分服务,能够完结小而美,做到快速迭代。那么另外一个V ; P ` g [问题就来了,杂乱的跨服务事务怎X O p V U 7 r +么处理呢?这时分就需求对服务进行拼装。
如图所示,这儿的 Node Proxy 做了两件事,分别是输出 API 和烘托辅佐。
- 输出 API:前端的异步 Ajax 恳求; $ R % / m l %能够直接拜访 API。
- 烘托辅佐6 u P y E : v:假如是直接烘托,或许选用 BigPipe、WebSocket 协议等,需求在服务器端拼装 API,然后再将成果回来给浏览器$ 8 | X r }。
所以 API 后边还有一个服务拼装,在微服务架构十分盛行的今日,将服务拼装放到 Node Proxy 里的好处尤其显着,既能够提高前端开发功率,又能够让后端愈加专心q u | 5 F ` # D于服务开发。假如前端团队足够大,还能够专门组建一个 API 小组,从事与服务集成相关的工作。
3.9 API网关
Node.js 擅长 I/O 操作,其 http 模块^ j 1和 stream 模块组合运用时十分适宜作为署理软件。一般,编写很少量的代码就能够完结一个功用强大的署理。
API 网关中有两个重要功用,恳求转发和跨域 JSONP 支撑。
const http = require('http');
httpK 3 | F ? Q , 6.createServer((req, res)=>{
if(re1 0 4q.url === '/remote'){
res.writeHead(200, {'content-type': 'text/plain'});
res.F 8 [ : s r D 3end('hello, remote page');
}else{
proxy(req, res)
}
}).listen(80, ()=&@ ` i % agt;{
console.log('se0 % W - : nrver is running at 80')
})
function p9 I v L Q k Broxy(req, res){
const options = {
hoo Y j % z T R { st: req.host,
pov f . j 2 ! 7 ] [rB - s Ct: 3000,
h! = |eaders: r6 C teq.headers,
age| { hnt: false,
method: 'GET'
}
let httpProxy = http.request(opQ d F mtions, (response)=>{
response.pipe(res)
})
}
关于跨域 JSONP 支撑,首先要了解以下几点。
- 跨域最通用的做法是选用 JSONP,关于 API 接口而言,将原有的 API 包装一下即可,但关于这样一个极端简略的包装,开发者往往会预估 0.5 人/天时刻,而且提测布置还需求时刻,所以让后端来做这件事就显得很不适宜。
- 最简略的做法是在页面地点的 Node.js 服务器上运用 Node.js 作为客户端来进行z 7 G恳求,最后将恳求成果以 JSON 或 JSONP 的方法回来。很多公司都是这样做的,十分简略。
- 选用上面所说的方法时,页面 URL 假如被 Nginx 重写了几次,是无法找到实在的 Node.js 服务器的(不是不能,是代价极高),那么此刻该如何去做呢?很简略,将页面服务和 node-proxy 转成同域的就能够了,用 Nginx 再适宜不过了。
- 上+ l 9 l k m [ | 面的处理方案看起来很好,可是多了一层 Nginx,为什么必定q S /要将页面服务和 node-proxy 转成同域的呢?详细该怎么做呢?很简7 B y略,让 node-% / %proxy 作为独立域名供给 JSONP 服务即可,做到页面和接口别离。
最终,咱们能够经过node服务署理依据实际状况发送json数据和jsonp数据
3; # S / ( p 4 I e.10 Serverless
Serverless 是一种依据互联网技能的架构理念,选用函数即服务(Function as a Service,FaaS)架构理念,让开发者只重视运用逻辑,而不用将全部功用都在服务端完结,经过组合多个函数的功用来完结运用程序逻辑。选用 Serverless 架构能够让开发者在构建运用的进程中无须重视服务器运维,有效节约开发本钱,其E [ g优势总结如下。
- 节约运用本钱。
- 简化设备运维进程。
- 提升可保护性。
在 Node.js 的世m y l ~ $ A R }界里,每个文件都是一个模块,那么集成 ServerM S 2 *less 概念能不能让每个文件都成为一个服务呢?经过预定的各 ) k : y ? [ *种 API SDK,一致自动化运维环境,是不是能够让开发更简略呢?
关于 Node.js 运用落地,能够先开发部分功用,也能够花一些精力将完整的开发流程打通,关于? f ; T ) _ j公司的整体架构对错常有利的。如图 3-15 所示,从 Mock API 开端,假如有对应的 Serverless 服务完结,c t S 7 : # p D能够直接切换F 7 ` + & z _。但现在各个结构都没有在减少运维本钱上做出更多努力,略显可惜。假如未来都一致到 Service Mesh 上,让前端开发人员不再忧虑运维难度大的问题,将更多精力投入到事务开Y & 6发上,便能够拓展前端的事务鸿沟,完全承担 R0 O % a 2PC 服务以外的一切工作也是有或许的。
3.11 更多运用场景
- 作为根底设施用于前端开发。
- 作为指令行辅佐东西。
- 用于移动端(Cordova)和 PC 端(NW.js 和 Electron)。
- 完结前端组件化,完结组件的打包构建,添加 HTTP 署理等功用。
- 用于架构规划,完结% , x前后端别离。
- 功能优化,反爬虫与爬虫。
- 完结全栈。
3.12 学习方针
- 玩转 npm、Gulp 这样的前端东西类(此刻仍是前端)。
- 运用 Node.` K p 6 A { c : .js 进行前后端别离(此刻仍是前端)。
- 把握 Express、Koa 这类结构。
- 把握 Jade、EJS 等模板引擎。
- 运用 Nginx。
- 玩转后端异步流程处理。
- 玩转后端 MongoDB、MySQn : hL 对应的 Node.js 模块。