引言
我真的很爱Nestjs,那是一种很纯粹、很理性的爱,四年了,我每天都在用它…哦,不对,是我们都在用它。
四年前,在那场剑拔弩张的技术选型会议上,经过十几轮Battle,楼主力排众议将Nestjs推向边缘计算平台的大舞台…
技术选型大PK
屏幕前的你或许也参与过技术选型,搞软件开发技术选型无非就是下面列举的,老哥们看看你们属于第几种?
单枪匹马梭哈型
不超过5人、规模非常小的技术型公司(公司地址大多是某公寓1号楼1单元7层404室),你作为其中一员多面手,承担了软件生命周期的全过程管理角色…选哪个技术,你说了算.
唇枪舌战battle型
楼主所在的公司稳坐某行业的头把交椅,公司内部开发人员无论从数量和成分来说都相当之复杂,可谓是各路武林好汉聚集,每个人都一身绝活…
有一众干了几十年驱动协议开发的C++大伯、信奉Spring为天下第一框架的Java爱好者,当然还包含一批学了几天Nodejs就自封为全栈的前端开发者…在这样的公司,做任何的技术选型,都会得罪人。很多时候,还没等你开口,就有人反对…
对,你没看错,这种团队里是没有一言堂。那楼主作为团队里唯一一名具备Java、Nodejs、C++(大学期间研究过几个月)、前端这4种技术栈的全能型储备总工(好吧,还有一个已经服役了20年的正式总工)
借助自己与生俱来的胆识力、智慧力、表达力,以及对人情世故的拿捏,通过下面几个维度的数据分析,成功碾压说服了他们…
资源占用
楼主参与的是大型的分布式边缘计算平台,边缘计算两大特点:计算快、资源占用少。我们开发的服务不仅要能运行在云端,要必须支持在内存不到8G的设备盒子里,你们知道现在JAVA程序有多大吗?但凡是跟Spring家族沾点边的,起步1个G内存…
下图是我们用Nestjs开发的A服务和用Springboot开发的B服务的资源对比(A比B服务业务更复杂,代码量更大)
虽然,我真的很爱Java,楼主现在具备的编码思想、设计理念很多都是Java给予我的,但是我们做技术的,尤其是我这种总工级别(储备型嘿嘿),理性与合理是我们头上的一把刀,时刻约束着我。
业务分析
在我们平台内包含了非常多的服务,真正提供边缘计算能力的服务我们选的是C++这种更底层、计算效率更高、资源占用更少的语言,而剩余的无状态管理类服务对计算能力要求不高,更多的是操作系统IO的读写。
Nodejs这门语言就特别适合做无状态、IO读写、少量计算型后台服务的开发。楼主曾经实测,2核CPU、4G内存的资源背景下,一个Nodejs进程(叫服务也可以)读数据库并响应给客户端这么一个简单的场景,吞吐量可达到XXX次…这是何等的卧槽…
注意:这里出现了几个关键词,计算型服务、无状态服务、操作系统IO、吞吐量(详见本文后面的码优集合)
人情世故
有人的地方就有江湖,有程序员的地方就有鄙视链。这句话不是我说的,我也是听别人说的。
通过上面2项的分析,Nodejs已经在资源占用方面碾压了Java语言。虽然楼主公司的程序员都是自认为能发明框架的牛逼人物,但是“时间紧、任务重”,这6个字我想屏幕前的你肯定不陌生。
楼主必须选一个合适的Nodejs框架,来提升团队开发的效率、可维护性,再加一些人情世故。其实,楼主大可以选择Express这个好像最流行的框架,为什么?因为它流行啊。可是,我们毕竟是一个团队,团队开发一开始就必须把规范和约束制定好
Nestjs相对Express,在规范约束方面大出一个Vue…为啥?因为…还是看图吧,楼主的确是个喜欢画图的人…
Express有没有规范?当然也有,但是更多的是属于文档约定规范。约定式的规范就会有人不遵守,而框架自身规范,好吧,你不遵守的话,你代码都跑不起来。
不可否认JS语言非常灵活,比如下面这段非常飘逸的代码:
function getMen(response){
let arr=[];
let obj = response.data;
let user = obj.user;
user.forEach((j)=>{
if(j.sex == 1){
arr.push(j)
}
})
return arr;
}
楼主凭借十几年的经验,大概能猜到arr里面的数据,但是具体包含哪些字段,可能只有写代码的老哥自己知道,这段代码如果不运行,神仙都不知道arr是个什么鬼?
这也是为什么很多JAVA、C++程序员不喜欢JS的原因,因为太黑盒了…但是,Typescript来了!!!
当我在技术选型会上秀出下面的代码时,大家都直呼卧槽,这不就是JAVA写代码的方式吗?
type MyResponse={
data:Obj
}
type Obj = {
user:Array<User>;
};
type User={
sex:UserSex,
age:number,
name:string
};
enum UserSex{
man=1,
women=2
};
function getMen(response:MyResponse):Array<User>{
let arr:Array<User>=[];
let obj = response.data;
let user = obj.user;
user.forEach((j)=>{
if(j.sex == 1){
arr.push(j)
}
})
return arr;
}
尤其是下面的代码出现的时候,甚至有人流出来激动的泪水,特么不就是Springboot么?哥,听你的,就选Nestjs
@Controller('users')
class UserController{
@Get()
async getAll(){
return [];
}
}
看到这里,很多从前端转过来的同学可能会比较懵逼,你听哥一句话:不怕。有些人可能还去专门学习typescript之类的,我告诉你,根本不用!你就关注我,我会在潜移默化中让你掌握typescript。
至于代码里面的 “@Controller”,好吧,你们经常群里是不是会 @XXX
懂了吗,就是提醒Controller这个人,请注意查收群消息,有个叫users的来了,把它登记下…
上述是整个Nestjs系列的“开山刀”,从现在开始请大家跟紧步伐,我会尽可能真实的还原Nestjs构建企业级边缘计算平台的过程。
各位千万别慌,这些知识我会用最浅显易懂的语言和图形化方式灌输给你们,根本不会涉及什么看似很高端的XXX底层原理之类的,请记住楼主的一句话,技术千千万万,如果你能在特定的场景选择合适的技术并正确的使用,就已经很牛了。
举个例子,我见过90%的开发人员选择了Kafka作为消息总线,可是他们的业务从来不存在队列的需求,
再比如我接触的99%的开发人员选择了Mysql作为存储,可是他们的数据几乎都非常零散的配置型数据…
好了,各位 let’s get started!!!
下载Nestjs
嘿嘿,没想到吧,我直接就下载Nest准备开撸了…,先不要管那些Nestjs概念好吗?让我们放轻松,来一首杰伦的反方向的钟
脚手架
nest提供了 Command Line Interface"=cli(命令行界面或者脚手架),把这个cli的全称请记住,要处处体现我们的专业。cli的作用就是提供了一些开箱即用的命令,帮助开发者更快速的创建一些目录、文件之类的。
npm i -g @nestjs/cli
@意味着安装到你电脑的全局环境,这样无论你在任意操作系统目录下执行nest命令,操作系统都认识,99%不会出现 nest command not found…
Nest命令
Nest安装完成后,你电脑里就注入了Nest这个全局命令,楼主的电脑是windows系统,我们现在看看nest命令都有哪些指令,这里又有一个细节,几乎99%的命令都包含 帮助 功能。
-h 或者–help 或者 --h,逃不出这三个选项,现在我们打开系统命令行,输入下面的指令看看
nest -h
所以说做开发,英语真是必备项,屏幕前的各位英语肯定都很牛逼,我就不翻译了,注意看第二个红框里面的new指令:用来创建你的Nest应用。
nest new edgeManagement
非常贴心啊,竟然问我喜欢NPM还是YARN?选NPM吧,注意哈,选择是用键盘上下键,确定是Enter键…然后各位去上个厕所吧,楼主现在每天喝8杯水,有时候尿频…
注意看里面的Donate(抖内特)这个单词,屏幕前的你估计Donate了不少主播吧,没错,就是打赏的意思,记住了!
大功告成!我们的边缘计算平台目前已经走出了第一步,注意看上图的dependencies,楼主不用研究Nestjs的架构,单看这个依赖项以及命名就能分析出框架的内部结构,一般叫COMMON的就是提供一些通用能力,CORE就是核心能力,platform就是跨平台。这种架构是市面上90%开源框架的雏形…由北向南形成依赖关系
目录结构分析
几乎所有的后端框架启动的入口都与 main 这个单词有关,比如Java和C++的main方法,nest提供的是main文件
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
很经典的单词 bootstrap(步特斯拽噗) 计算机Bootstrap是指通过一系列步骤,逐渐启动一个系统或应用程序的过程,它比你们最喜欢的 init 或者 start 作用范围要更广.
再来看bootstrap函数体,非常经典的工厂模式创建某个东西,记住了各位,但凡出现xxxFactory就是工厂模式,楼主是一个非常在意细节的人,评判一个程序员的水平从他的代码命名就能看出端倪,下图是你们最喜欢的命名
启动
所有使用Nodejs语言开发的程序,启动命令都在根目录的package.json > scripts 中定义
nest内置了4个启动命令,后面章节大家会使用到这4个命令,我个人非常喜欢这种使用冒号来划分场景的命名方式
- start
- start:dev
- start:debug
- start:prod
现在,让我们打开命令行工具,输入最简单的命令,看看操作系统是否会创建一个3000端口的进程
npm run start
启动成功,现在我们用浏览器访问一下3000端口,看看返回什么
非常国际化的 Hello World,注意看 X-Powered-By=Express 这个http 响应头,说明Nest内部肯定用到了Express,不是吗?
目前有些HTTP 服务器会给客户端响应 X-Powered-By=Express 这个字段,意思是告诉客户端,我是哪种服务器。比如 X-Powered-By = nginx,X-Powered-By = tomcat…好吧,楼主的确很细…心
Hello World
为什么页面会显示 Hello World ? 请大家跟着我一起,接下来的操作你们以后开发后端服务会经常用到。打开vscode万能的搜索,输入 Hello World 查看有哪些文件与这个字符串有关系
原来是app.service.ts文件内返回的,接下来使用鼠标双击选择 AppService ,之后按下右键,选择 go to references(意思是查看引用)。目的是从底至上查看完整的调用链
终点来了,通过我们一步步的 go to references,最终可以画出下面这张图
很关键的一张图,后面我们自己写的所有代码都遵循上图的调用链,细心的同学肯定发现了围绕app这个单词
出现了3个文件。没错,这个就是Nest框架的根基。为什么叫app,而不是root? 我猜可能Nest的作者还是受到Express的影响…
- app.module.ts
- app.controller.ts
- app.service.ts
好了,至此我们第二章节完成了Nest工程的初始化工作,下一章你们将学到关于模块的概念以及我们边缘计算平台的第一个自定义模块-边缘工程 。各位,2-3天后我们再见面!!!
结语
好了各位朋友,这就是我个人的写作风格,关注我,你会发现你的设计能力、编码规范、画图能力,甚至包含英语都会全方面的提升.本文属于Nest系列的开山刀,后续文章将带大家逐渐开始真正的边缘计算平台实战,围绕Nestjs为主线,为了保证内容的真实性、完整性,屏幕前的您还将额外学到以下知识(是不是很兴奋…):
码优集合
欢迎大家来到码优集合,作为惯例,楼主会在每篇文章的末尾给各位补充一些软件行业的小知识,我会用图形化的方式将复杂的事情给你讲明白,好了,let’s get started!
计算型服务 VS IO密集型服务
首先,屏幕前的你接触的99%的后端服务都属于IO密集型或者说IO型居多,你都谈不上密集。
所谓IO就是操作系统的输入input和输出output,操作系统里面所有磁盘上文件的读写、网络数据的传输都属于IO行为。
举个例子,你用nodejs封装了一个方法,该方法打印你本地电脑F盘的“精选图片”。这就是IO操作
//示意代码
const fs = require('fs');
fs.readdir('F:/精选图片', (err, files) => {
if (err) throw err;
console.log(files);
});
既然气氛已经烘托到这了,我就顺道给大家讲一下Nodejs的IO是怎么实现的,其实非常简单。请看下图:
如果你能看懂上面这张图,那么下面Nodejs官方给出的架构图,你也就理解了
屏幕前的你,学到了吗?是不是很好理解
无状态服务 VS 有状态服务
说到状态,我拿DOTA这个游戏来举例(LOL游戏也适用):
请问,1分钟恢复之后,你现在几级?什么装备?如果DOTA服务器是有状态服务,那么当恢复后,你的装备与等级与崩溃前保持一致,如果是无状态,好吧,你白玩了10分钟…
但是,你们接触到的90%的后端服务都属于无状态服务,数据都持久化存储在磁盘上(数据库、文件等),如果服务突然挂掉,客户端调用服务接口无非是无法连接而已
吞吐量
吞就是吸进去input,吐就是吐出去output。吞吐量一般来说衡量某个后端服务单位时间能处理的业务量。各位都开车走过高速公路吧,看看下图你就明白了:
同时刻有6辆车,但是理论上实际只能每秒过3辆车
好了,各位老铁,我真的累了,一口气写了这么多,不知道你们是否喜欢“码优集合”这个扩展板块,如果喜欢,请留言给我,我会继续在后续文章里给大家多讲讲这些理论,带你们多见见世面…ok,各位,下一章见。