自 2015 年推出 NGINX JavaScript 模块(njs,当时名为 nginScript),并于 2017<.htmla> 年正式发布以来,我们已在数十次版本更新中持续添加新功能并改进实现。通常,我们会等到 NGINX Plus 发布新版本时再介绍新版 NGINX JavaScript 的功能,但版本 0.7.7 实在令人期待,这次我们决定提前分享!
njs 0.7.7中的重大增强功能有助于进一步提升NGINX配置的模块化程度、条理性和可重用性:
- 现在可以在适用的上下文中声明njs代码,而不必进行全局声明,让自定义代码更接近其使用位置。
- njs代码本身的钩子支持根据执行上下文修改行为。
- 新的
fs.FileHandle对象可提高文件操作效率。
要详细了解njs并查看我们提供示例代码的用例列表,请阅读我们博客上的《利用NGINX JavaScript模块,为每个请求发挥JavaScript的强大功能与便捷性》。
有关njs 0.7.7所有新功能和错误修复的完整列表,请参阅《变更》文档。
在局部上下文中声明JavaScript代码和变量
在以前的njs版本中,必须在顶层js_import、js_path、js_set和js_var指令所在的http或stream上下文中导入JavaScript代码并声明相关变量。这相当于在主文件顶部声明全局变量。但实际调用JavaScript函数和变量的指令位于子上下文中。例如,HTTP js_content指令位于location{}块中,而Stream js_access指令位于server{}块中。这会导致两个问题:
- 对于阅读配置的人员来说,
http和stream上下文中的声明基本上属于干扰信息,因为其中并未说明相关代码和变量实际在何处使用。 - 在子上下文中,无法直观看出代码和变量是从何处导入和声明的。虽然我们建议仅在主配置文件(
http{}和stream{}块,并使用nginx.conf)中包含include指令,从/etc/nginx/conf.d和/etc/nginx/stream.d目录读取按功能划分的较小配置文件,但NGINX配置非常灵活,可以在多个文件中包含http{}和stream{}块。如果多人共同维护NGINX配置,且未必始终遵循既定约定,这种做法尤其容易引发问题。
在njs 0.7.7及更高版本中,可以在使用代码和变量的上下文中导入代码并声明变量:
- HTTP:
- Stream:这些指令既可出现在
server上下文中,也可出现在stream上下文中:
将特定用例的所有njs配置集中在一个文件中,还能提高代码的模块化程度和可移植性。
例如,在旧版njs中,添加新脚本时,必须同时修改nginx.conf(添加js_import,并可能添加js_path、js_set和js_var),以及调用JavaScript函数的文件(此处为jscode_local.conf)。
正在加载代码示例…
正在加载代码示例…
在njs 0.7.7及更高版本中,与util函数相关的所有配置均位于同一个文件中:jscode_integrated.conf:
正在加载代码示例…
根据执行上下文修改行为
njs 0.7.7中的多项新功能支持根据JavaScript代码的执行上下文(处理阶段)调整其行为。
HTTP r.internal 属性
HTTP r.internal属性是一个布尔标志,对于内部请求,该标志设置为“true”(此类请求由包含location{}块中的internal指令处理)。当脚本使用可在内部和非内部上下文中调用的通用事件处理程序时,可以使用r.internal标志执行不同的逻辑分支。
以下请求归类为内部请求:
- 由以下指令重定向的请求:
error_page、index、random_index和try_filesdirectives - 由上游服务器的“
X-Accel-Redirect”响应标头重定向的请求 - 由以下项调用的子请求:
auth_request和mirror指令、ngx_http_addition_module 模块中的指令,或服务器端包含(SSI)的includevirtual命令(由 ngx_http_ssi_module 模块支持) - 由
rewrite指令更改的请求
改进的s.send()流方法
在早期njs版本中,Stream的s.send()方法依赖于上下文,因为其数据发送方向取决于调用该方法的回调所在位置(上游或下游)。该方法最初是为同步回调设计的,因此可正常用于同步回调,但无法用于s.send()等异步函数,例如ngx.fetch()。
在njs 0.7.7及更高版本中,方向存储在单独的内部标志中,之后s.send()便可使用该标志。
使用新的fs.FileHandle()对象提高文件操作效率
文件系统模块(fs)用于执行文件操作。fs模块中的新FileHandle对象是数值文件描述符的对象封装。FileHandle对象的实例由fs.promises.open()方法创建。
使用FileHandle对象获取文件描述符,该描述符可进一步用于:
- 对文件执行
read()和write()等函数 - 打开文件并在指定位置执行读取和写入操作,无需读取整个文件
已实现 FileHandle 的以下属性(有关每个属性的必需参数和可选参数,请参阅文档):
filehandle.fdfilehandle.read()filehandle.stat()filehandle.write()filehandle.write()filehandle.close()
以下方法已更新,现支持FileHandle(有关各方法参数的信息,请参阅链接的文档):
使用njs增强配置
借助njs 0.7.7,团队可以更轻松地处理和共享njs代码。njs指令扩展了适用上下文,让您可以更直接地使用自定义JavaScript代码增强NGINX配置。您可以由此着手构建API网关、反向代理或Web服务器,使其不再只是又一个中间件或边缘组件。通过JavaScript、TypeScript或第三方node模块,您可以将其融入应用,而无需在技术栈中添加其他组件。只需NGINX即可!
有疑问?加入NGINX Community Slack,并查看#njs-code-review频道,了解更多信息、提出问题并获取有关njs代码的反馈。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
