Node.js会永远比Golang慢吗?

感觉上每周都会出现一个新的Node.js“ Web框架”,这种框架的运行速度比之前的要快。 每个人都知道Express速度很慢,但是下一个框架是否能够真正改善Node.js I / O子系统的性能? 它唯一能做的就是消除Express创建的系统上的过多负载。 没有谈论改善一些基本的东西。 实际上,为了从根本上改善这种情况,您需要进行更深入的研究,而不是在Node.js之上添加新的抽象。

图片

在Node.js平台上创建运行比今天快得多的服务器应用程序需要什么?

形势分析


Express是Node.js最早的Web框架之一。 它基于该平台的标准功能,为开发人员提供了围绕应用程序概念构建的便捷界面,并允许您管理URL路由,参数,方法等。

Express很简单;它可以帮助程序员快速开发应用程序。 他唯一缺少的就是表现。 经常出现的项目(例如Fastify)努力为开发人员提供与Express相同的功能,但性能损失较少。 但是它们本身就是在系统上增加额外负载并严重影响性能的原因。 它们受到Node.js平台可提供的功能的严重限制。 与竞争对手相比,它所提供的收益不多。


每秒不同服务器处理的HTTP请求数

注意红线。 这是Node.js的最大平台。 对她而言,无论他们的名字中是否包含“快速”一词,他们都无法越过这条线。 当将Node.js平台与其流行的替代品(例如Golang)进行比较时,这实际上是一个非常低的性能极限。

幸运的是,Node.js支持C ++附加程序,Google V8绑定程序,它们使您可以绑定JavaScript和C ++,并允许您从JavaScript调用任何机制,即使这些机制不是由Node.js.平台提供的也可以。

这样就可以扩展和改进JavaScript应用程序的功能,使您达到新的性能水平。 这样一来,JavaScript程序就可以从Google V8引擎中挤出所有可能的内容,而不仅限于Node.js开发人员发现的足够功能。

关于µWebSockets.js


本月初,我发布了一个新项目-µWebSockets.js 。 GitHub用于托管其代码,而不是npm,但是您可以使用npm将其安装到Node.js,如下所示:

npm install uNetworking/uWebSockets.js#v15.0.0 

要使用µWebSockets.js,不需要编译器。 支持Linux,macOS和Windows。 系统的初始版本为15.0.0,版本编号是根据语义版本控制的规则进行的。

µWebSockets.js是使用JS编写的后端应用程序的备用Web服务器。 它由大约六千行C和C ++代码组成,并且明显优于Golang编写的最佳解决方案。 因此,bitfinex.com交易所已将其两个交易API(REST和WebSocket)移植到µWebSockets.js,并逐步将其引入生产环境。 Bitfinex的Paolo Ardoino指出,这是一个很棒的项目。 我想说的是,我之所以能够发布µWebSockets.js,完全是由于BitMEX,Bitfinex和Coinbase向我提供的支持。

µWebSockets.js的功能


µWebSockets.js是根据Apache 2.0许可证发行的新项目,该项目是所谓的“ uws”的延续。 这个项目是Google V8的完整堆栈,从操作系统的内核级别开始,完全替代Node.js的标准功能,并代表Node.js的稳定,安全,符合标准,快速,轻量级的I / O子系统。 使用µWebSockets.js,这就是JS应用程序与操作系统的交互。


JS应用程序与使用µWebSockets.js的操作系统的交互

如您所见,该项目由几层组成。 每层仅取决于前一层。 该体系结构简化了错误的识别和纠正,并且由于实施了新功能而简化了扩展解决方案的工作。

应该注意的是, µSockets层本身包括三个子层,这三个子层是用于处理事件和网络的机制以及用于保护数据的工具。 这允许在必要时替换解决方案的各个部分,向系统中添加某些功能的替代实现,而无需在更高级别上更改代码。

例如,如果您需要用某种东西代替OpenSSL,只需将ssl.c文件及其六百行代码更改为ssl.c的代码即可。 但是,系统的其他层甚至都不知道SSL是什么。 除了方便将系统的某些部分替换为其他部分之外,这种方法还导致错误检测过程的简化。


Μ套接字内部子层

此处介绍的体系结构与Node.js中使用的整体体系结构非常不同,后者在同一源代码文件中可以找到对libuv的调用,与系统一起使用的命令以及对OpenSSL和V8的调用。 在Node.js中,所有这些都是混合的,没有人提出隔离此平台的各个部分的方法。 这大大增加了对Node.js进行重大更改的过程。

关于µWebSockets.js的开发


这是使用µWebSockets.js的极其简化和简化的示例,其主要任务是演示系统的基本功能。

 /* SSL-   */ uWS.SSLApp({   key_file_name: 'misc/key.pem',   cert_file_name: 'misc/cert.pem',   passphrase: '1234' }).get('/hello', (res, req) => {   /*    */   res.end('Hello World!'); }).ws('/*', {   open: (ws, req) => {       console.log('A WebSocket connected via URL: ' + req.getUrl() + '!');   },   message: (ws, message, isBinary) => {       /* OK   false          *     */       let ok = ws.send(message, isBinary);   },   drain: (ws) => {       console.log('WebSocket backpressure: ' + ws.getBufferedAmount());   },   close: (ws, code, message) => {       console.log('WebSocket closed');   } }).listen(port, (token) => {   if (token) {       console.log('Listening to port ' + port);   } }); 

从某种意义上讲,可以说使用SSL的µWebSockets.js可以绕过Gorilla WebSocket,它是Go上WebSocket协议的一种实现,没有SSL。 也就是说,事实证明,在某些情况下,JS代码使用SSL交换消息的速度甚至比在没有SSL的情况下用Go编写的代码更快。 我相信这是一个很好的结果。

快速的WebSocket协议实现


在许多方面,可以将Socket.IO视为实时等效于Express。 这两个项目都是很久以前出现的,与他们合作很容易,很受欢迎。 但是,除其他外,它们也很慢。


各种WebSocket实现

Socket.IO开发人员帮助解决的任务简化为发布消息和订阅消息的功能的实现,以及发送和接收消息的功能。

同时,值得注意的是,使用了一些备用机制来处理WebSocket协议,因为浏览器长期以来一直支持该技术。 公司代理无法解释SSL流量,它以与任何HTTP流量相同的方式通过它们;因此,通过SSL使用WebSocket协议不会阻止相应的流量。 可以提供支持WebSocket的备用机制,但使用它们毫无意义。 它们只会不合理地增加决策的复杂性。

µWebSockets.js的目标之一是为开发人员提供与Socket.IO中相似的功能,以便µWebSockets.js可以完全替换Socket.IO,而无需任何更高级别的包装器。 。 如果未使用某些特殊的非标准协议,则可以这样做。

许多公司在使用WebSocket时都无法发布和订阅消息。 应该注意的是,在所描述的µWebSockets.js版本中,这些功能没有得到足够的重视,但是现在正在对其进行认真的工作。 结果将非常快(测试表明µWebSockets.js已经比Redis更快)。 因此,请继续关注。

总结


目前,μWebSockets.js正在开发中,新功能已添加到项目中,错误已修复。 要消除那些新程序的第一版所特有的小缺陷,将需要一些时间。 请记住,这是一个大型项目,由成千上万行用C和C ++编写的代码组成,这些代码存储在三个存储库中。 是JavaScript包装器-uWebSockets.js。 这是用C ++编写 Web服务器-uWebSockets。 是用C编写的基础库-uSockets。

有问题的项目由公司使用,所使用的程序在I / O子系统上造成了巨大的负担。 在这些公司中,完全自然和显而易见的稳定性和安全性是他们使用的软件的最重要特征。

亲爱的读者们! 您打算在项目中使用µWebSockets.js吗?

Source: https://habr.com/ru/post/zh-CN439976/


All Articles