初识 nodejs
nodejs在2010年就活跃于各大网站,但是我在2015年才开始知道这个东西,因为当时公司是做媒体的,需要不停的采集一些数据同步到mongoDb中,就使用了nodejs写服务,但当时那还是别的大神写的代码,像我等小菜鸡根本无法企及。
那时才知道原来javascript还能做服务。之前的认识就停留在HTML中的脚本语言,比如,动态处理一些Dom元素,添加属性、修改样式、元素间组织等,最多发送一下get、post请求给后台服务,从没想过js也可以像java、C++等一样,可以作为服务端,处理请求、文件操作、数据库查询、异步操作等,并且请求处理速度还要优于传统的javaWeb。现在公司要求做一个restApi,这就又把nodejs拉回了我的视线。
概念:nodejs是依赖于Chrome的V8引擎的一套javascript运行环境。
既然是基于V8引擎的,那么我们先了解一下这个v8(https://v8.dev/docs),摘取了部分信息做了简单概括:谷歌的V8引擎是一个开源的高性能js引擎,使用C++编写,在谷歌浏览器、NodeJs等很多地方都有使用。它可以单独运行也可以嵌入到任意的C++程序中运行(这使得v8引擎和c++无缝融合)。 v8引擎可以执行js源代码,可以给对象分配内存,并且能像java一样垃圾回收(v8引擎的开发团队leader之前是开发jvm团队的核心成员)。
从GitHub(https://github.com/nodejs/node)上可以看到nodejs项目结构:
由此可见,宣称的nodejs实现的种种功能,实际上是c++做的底层,然后这个c++的项目又嵌入了v8引擎的源码,使得能在javascript平台上运行c++实现的功能,达到了借助c++强化javascript的目的。但是这并不是全部,nodejs宣称的“非阻塞”、“单线程”、“异步I/O”,高并发并没有体现,它得益于js本身的,基于事件驱动的特性(类似,onload、onclick、ondbclick、onmouseover...),并且针对此特性使用c++做了足够的优化(libuv等),于是就有了网上多如牛毛的nodejs高并发架构描述:
- Application:调用方,写js代码
- V8:js代码一次性编译成机器码,并调用对应nodeAPI
- Bindings:看作一个adaptor,例如Windows、Linux、Mac等不同系统都有自己的适配器,跨平台的核心内容
- Libuv:任务执行库,单线程、高并发、异步IO的核心实现
回顾一下js:单线程,(HTML5中新增了webWorker内容,允许在主线程执行期间插入耗时操作,但不会阻塞主线程的执行,不会干扰页面,且子线程受主线程控制,不得修改DOM元素,因此不违背js是单线程的),如果有需要事件驱动的,也就是需要回调的,主线程会顺序执行,将此类函数会加到event stack中,待主线程所有语句都执行完后才会去循环遍历event stack,取事件去执行。
setTimeout(function (){console.log(2);}, 1000);
setTimeout(function (){console.log(3);}, 1000);
console.log(1);
console.log(4);
// ================================
console.log(1);
console.log(4);
setTimeout(function (){console.log(2);}, 1000);
setTimeout(function (){console.log(3);}, 1000);
两种效果一样:
1
4
2
3