NJS介绍
1,什么是NJS
njs是nginScript的简称,是为了 NGINX 和 NGINX Plus ⽽开发的 JavaScript 实现,它被设计⽤于在服务器端处理请求。它通过融⼊JavaScript 代码对 NGINX 的配置语法进⾏扩展,以便实现复杂的配置。
2,NJS能做什么
nginScript 同时⽀持 HTTP 和 TCP/UDP 两种协议,所以它的应⽤场景很⼴。
⽣成⾃定义的⽇志格式, ⽇志⾥可以包含普通 NGINX 变量⽆法表⽰的值。
实现新的负载均衡算法。
通过解析 TCP/UDP 协议,实现应⽤层的粘性会话。
检查和修改 HTTP 请求消息和响应消息的 body(已经⽀持 TCP/UDP)。
从 nginScript 代码⾥发起 HTTP ⼦请求。
编写 HTTP 认证处理器(已经⽀持 TCP/UDP)。
读写⽂件。
除此之外还不断有新特性再逐渐加⼊进来
3,NJS 对决 Lua
多年来,NGINX社区创建了很多编程式扩展,Lua是其中最受欢迎的⼀个。Lua被作为NGINX的⼀个模块,典型的就是OpenResty,基于nginx 做了很多插件。
但lua语⾔并不是⼀种特别流⾏的开发语⾔,⽐较⼩众。⽽我们为了解决⼀个问题去专门学习⼀门语⾔,门槛相对过⾼。所以nginx的官⽅团队推出了NJS。
但⽬前在成熟度上,njs和lua的差距还是蛮⼤的,⽐如访问redis,njs⽬前⽆法⽀持。
4,NJS 容易被误解
NJS != JavaScript 更不是nodejs
njs是JavaScript/ECMAscript的⼦集 。它实现了⼤部分的JavaScript语⾔的能⼒,没有完全遵从ECMAScript标准,同时抛弃了JavaScript⽐较难懂的部分。
njs不是通过V8引擎实现的 。⽽是通过⼀个更⼩、能耗更低、更符合nginx应⽤场景的⼩虚拟机(VM)来实现。可以理解为nginx为其实现了⼀套⾃⼰的词法解析。
njs是跑在nginx的配置⽂件⾥ 。 ⽐如:f⽂件⾥。所以njs可以完成传统配置⽂件所能处理的所有事情,同时可以让配置管理动态化。这也是njs出现的最重要的原因。
Web端的JavaScript中的很多语法都不适⽤与njs中
简⽽⾔之,相⽐较lua,给⼤家提供了⼀个热度更⾼的语⾔实现⽅式。
5,NJS的设计原则
为了满⾜服务器端代码的执⾏需求,并与 NGINX 的请求处理架构保持兼容。njs的设计遵循了如下原则。
根据请求来创建和销毁运⾏时环境
nginScript 使⽤单线程执⾏字节码,可以实现快速的初始化和销毁。系统为每个请求创建⼀个新的运⾏时环境,因为不需要初始化复杂的状态和辅助组件,所以启动速度⾮常快。在处理请求期间分配⼀个内存池,请求处理完毕之后销毁内存池。这种内存使⽤模式避免了对象的跟踪和释放⼯作,也不需要使⽤垃圾回收器。
⾮阻塞的代码执⾏
nginScript 的运⾏时环境是通过 NGINX 和 NGINX Plus 的事件驱动模型来执⾏的。当某个 nginScript 规则在执⾏阻塞操作时(⽐如读取⽹络数据或向外部发起⼦请求),NGINX 和 NGINX Plus 会将该虚拟机挂起,直到阻塞操作事件结束。也就是说,规则的编写会变得很简
单,NGINX 和 NGINX Plus 会在内部把它们变成⾮阻塞操作。
只实现必要的语⾔特性
ECMAScript定义了 JavaScript 的规范。nginScript 实现了ECMAScript 5.1,以及ECMAScript 6中与数学运算相关的规范。实现⾃⼰的JavaScript 运⾏时给了我们充分的⾃由,我们可以优先实现服务器端需要的特性,忽略掉不需要的部分。
与请求处理阶段的深度集成
NGINX 和 NGINX Plus 把请求的处理分为不同的阶段。配置指令⼀般会在⼀个特定的阶段执⾏,本地 NGINX 模块经常利⽤这个特性检查和修改请求消息的内容。nginScript 通过配置指令把某些处理阶段暴露出来,从⽽能够控制 JavaScript 代码的执⾏。这种⽅式保证了本地 NGINX 模块的强⼤和灵活,同时保持 JavaScript 代码的简单性。
nginx 配置文件6,和其他语⾔插件相⽐的优势和劣势
优势:NGINX官⽅团队出品,2015 年 9 ⽉启动以来,有很多特性和核⼼语⾔⽀持不断被添加进来。
劣势:发展时间尚短,功能上还有所⽋缺。
7,在特来电中的应⽤
业务场景:saas化
对于特来电的web运⾏平台,我们有很多saas化客户。假如平台站点是x.teld
⽽saas⽤户域名为:
d
运⾏结构如图:
由于使⽤的是hash路由,转向url中携带#,所以没法通过配置实现动态化
这种结构有个最⼤的问题,就是每增加⼀个saas⽤户都要部署⼀个html以及配置
对⼤家来说,这是⼀种很糟糕的体验
我们开始尝试寻解决⽅案,开始选的是lua,但总感觉对于这样简单的场景,引⼊lua容器,有点过重,有点杀鸡⽤⽜⼑的感觉。通过对⽐最终采⽤njs来实现。
改造后如图:
过njs脚本来实现请求的变化。
⾸先在conf⽂件中对server_name采⽤正则表达式拦截
进⼊njs脚本,根据不同客户动态输出不同的内容到客户端。
经过调整,saas客户的增加不会对部署程序造成影响,⽬前上线半年,体验良好。
配置及部分代码
在配置⽂件中:
在saasControl.js中
8,总结
整体来讲,njs还是处于发育期,和lua在功能上⽐还是⽐较弱。
如果⽤nginx根据映射表来反向代理内⽹IP+端⼝,⽬前来说lua更合适。
但由于njs是nginx官⽅团队出品,长远来看,⽆论从质量还是功能上,都很值得期待。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论