您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

时间:2022-06-27 09:48:28  来源:  作者:老傅解码
理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

在过去的五个月里,我一直在我当前的项目中使用 Spring Webflux,我还编写了很多 Nodejs 应用程序,并且使用 Promise 样式编码(async/awAIt)的方式也几乎相同,而 Webflux 使用 Mono/Flux。

Nodejs 和 Spring Webflux 之间的区别是什么,因为它们都在解决同一个问题,专注于事件循环。

Node.js 是一个构建基于 Chrome V8 JAVAScript 引擎的事件驱动服务器应用程序的平台。

.NETty 是一个事件驱动的框架,用于在 Java 平台上构建服务器应用程序。

 

让我们看看基于以下几点的比较,了解设计方法和内部发生了什么不同之处?

线程模型

在决定任何框架之前,需要了解线程建模。

Nodejs:

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

  • Node.js并不是单纯的单线程,它用主线程处理所有请求,然后对I/O操作进行异步处理,交给其他线程去执行,避免了频繁创建、销毁和上下文切换带来的系统开销。下面来看Node.js的工作原理。
理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

从左到右,从上到下,Node.js 被分为了四层,分别是 应用层、V8引擎层、Node API层 和 LIBUV层。

应用层: 即 JavaScript 交互层,常见的就是 Node.js 的模块,比如 http,fs

V8引擎层: 即利用 V8 引擎来解析JavaScript 语法,进而和下层 API 交互

NodeAPI层: 为上层模块提供系统调用,一般是由 C 语言来实现,和操作系统进行交互

LIBUV层: 是跨平台的底层封装,实现了 事件循环、文件操作等,是 Node.js 实现异步的核心

Node.js在主线程维护了一个事件队列,接收到请求后,就将该请求作为一个事件放入Event Queue中,然后继续接受其他请求,当主线程空闲(没有请求接收) 的时候,就开始轮询事件队列

Webflux:

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

  • 接收客户端连接是一个独立的线程池。Acceptor接收到客户端TCP连接请求处理完成后(可能包含接入认证等),将新创建的SocketChannel注册到I/O线程池(sub reactor线程池)的某个I/O线程上,由它负责SocketChannel的读写和编解码工作。
  • Acceptor线程池只用于客户端的登录、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的I/O线程上,有I/O线程负责后续的I/O操作。

异步操作

Nodejs:

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

  • Nodejs 内部使用 Libuv 来处理异步任务。它将现代内核所能做的尽可能多的调度到操作系统内核。
  • 如果 Libuv 无法将任务委托给内核,则它使用其创建的线程池(默认 4 个线程)来处理工作。

Webflux:

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

  • 在 Netty 4 中,所有 I/O 操作和事件都由分配给事件循环的同一线程处理。
  • 而在 Netty 3 中,入站事件有一个单独的事件循环,在 I/O 线程池中处理,出站事件可能在 I/O 线程池或另一个池中。

事件循环结构

Nodejs:

理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计

 

  • Event Loop 有多个阶段来处理事件,它们是计时器、挂起回调、空闲和准备、轮询、检查和关闭回调。

Webflux:

  • 事件循环有它的任务队列。
  • 每当应用程序收到新请求时,它都会存储在 Java 堆中,其​中一个事件循环将从 Java 堆中选择它并进行处理。

事件循环中的任务调度

Nodejs:

  • 所有通过 setTimeout() 或 setInterval() 调度的内容都将在事件循环的计时器阶段进行处理。

Webflux:

  • 我们可以使用事件循环来调度任务。这里的事件循环继承ScheduledExecutorService执行线程池管理。
  • 如果我们直接使用 ScheduledExecutorService,那么在高负载下,这会带来性能成本,并且如果任务被频繁调度,可能会成为瓶颈。

CPU 利用率

Nodejs:

  • Node.js 应用程序在单个线程上运行。在多核机器上,这意味着负载不会分布在所有内核上。
  • 使用 Node 附带的集群模块,可以很容易地为每个 CPU 生成一个子进程。
  • 每个子进程都维护自己的事件循环,主进程透明地在所有子进程之间分配负载。

Webflux:

  • 如果我们需要运行一个长时间运行的任务,那么最好创建一个单独的线程执行器池并在那里处理它。事件循环稍后可以选择返回的结果,避免事件循环解除对长任务的阻塞。
  • 我们还可以增加事件循环实例来提高 CPU 利用率。

调整线程池

Nodejs:

  • Libuv 会创建一个大小为 4 的线程池。
  • 可以通过设置环境变量 UV_THREADPOOL_SIZE 来覆盖池的默认大小。

Webflux:

  • 事件循环线程池的默认大小是可用处理器的两倍。
  • 可以根据需要修改池大小。

处理背压问题

软件系统中的背压是使流量通信过载的能力。换句话说,信息流的生产速度超过消费速度。

Nodejs:

  • 被调用的 HTTP 服务器在 1s 后返回数据以模拟慢速后端。当等待后端返回的请求在 Node 内部堆积时,可能会导致背压。
  • 为了在流中实现背压,我们可以使用具有高水位标记的可读可写流来有效地处理数据生产者和消费者之间的背压。

webflux:

  • 背压的责任由 Project Reactor 管理。它在内部使用 Flux 功能控制发射器产生的事件。
  • Webflux 使用 TCP 流量控制来调节背压。
  • Flux 中提供了三种方法,我们可以使用它们来控制背压。
  • 选项 1:使用request(),消费者可以控制让发布者等到它收到新事件的请求。简而言之,消费者订阅事件并根据需求进行处理。
  • 选项 2:使用limitRange(),我们正在设置一次预取的项目数。即使消费者请求处理更多事件,该限制也适用。发布者将事件分成块,避免消耗超过每个请求的限制。
  • 选项 3:使用cancel(),消费者可以随时取消要接收的事件。我们可以取消订阅并稍后再次订阅以继续接收下一个事件。
  • 为了处理客户端和服务器之间的背压,我们可以Channel.isWritable() 通过调用 Channel.write()来检查是等待还是发送下一个事件,或者我们也可以列出fireChannelWritabilityChanged事件来决定何时向通道发送更多数据.

基于以上几点,我认为没有一个比另一个更好,因为两者都有一些优点和缺点。但在大多数方面,它们在性能方面是相同的。因此,可以根据技能可用性、团队技术方向、项目生态系统等来做出决定。



Tags:Nodejs   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Nodejs 的 CommonJS 规范实现原理
了解 Node.js Node.js 是一个基于 ChromeV8 引擎的 JavaScript 运行环境,使用了一个事件驱动、非阻塞式 I/O 模型,让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为...【详细内容】
2023-11-24  Search: Nodejs  点击:(201)  评论:(0)  加入收藏
NodeJS堆溢出的原因,及解决办法。
使用NodeJS开发的应用,如果需要处理大量数据,可能导致堆溢出。错误提示中,会有“JavaScript heap out of memory”,如下图:通过调试分析,会发现:在出错之前,其使用的内存量是一直增...【详细内容】
2022-12-11  Search: Nodejs  点击:(462)  评论:(0)  加入收藏
autojs的rhino和nodejs写悬浮窗对比
第一行:rhino// 这里是空的nodejs"nodejs ui-thread";"ui"和"ui-thread"是有区别的: ui: 用于显示界面(Activity)的情况,比如启动后展示一个Web页面用于用户操作,参见UI模块的文...【详细内容】
2022-09-23  Search: Nodejs  点击:(664)  评论:(0)  加入收藏
七爪源码:使用 NodeJs 观看文件系统
监视文件系统意味着监视特定目录或文件的更改。 有时您可能需要持续观察特定文件或目录的更改。出于这个原因,我们使用像 chokidar 这样的文件系统 Watcher 或内置的 NodeJs...【详细内容】
2022-09-17  Search: Nodejs  点击:(480)  评论:(0)  加入收藏
理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计
在过去的五个月里,我一直在我当前的项目中使用 Spring Webflux,我还编写了很多 Nodejs 应用程序,并且使用 Promise 样式编码(async/await)的方式也几乎相同,而 Webflux 使用 Mon...【详细内容】
2022-06-27  Search: Nodejs  点击:(635)  评论:(0)  加入收藏
挖洞经验之nodejs 中的漏洞技巧
零基础学黑客领资料搜公众号:白帽子左一关于原型链在javascript中,继承的整个过程就称为该类的原型链。每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又...【详细内容】
2022-05-20  Search: Nodejs  点击:(971)  评论:(0)  加入收藏
手写一个仿微信登录的nodejs程序
前言 首先,我们看一下微信开放文档中的一张图: 上面的一幅图中清楚地介绍了微信登录整个过程,下面对图上所示进行总结: 一、二维码的获得 用户打开登录网页后,登录网页后台根据微...【详细内容】
2022-05-06  Search: Nodejs  点击:(396)  评论:(0)  加入收藏
基于NodeJS的KOA2框架实现restful API网站后台
在此前写的文章“从零基础入门进行小程序开发实战”中,已经介绍过背单词的小程序,因为没有备案的服务器资源只能使用系统后台提供的缓存功能存储用户数据。缓存有大小限制,而且...【详细内容】
2021-07-27  Search: Nodejs  点击:(415)  评论:(0)  加入收藏
Nodejs读取Google Drive里面的文件
最近在工作中遇到了一个场景:要做一个静态的网站,里面的内容是由设计编写的.md格式的内容。设计将编好的文档统一放在常用的Google Drive里面,如下图 然后我需要将这些文档下载...【详细内容】
2021-06-09  Search: Nodejs  点击:(604)  评论:(0)  加入收藏
nodejs版本大文件之断点下载
框架语言:nodejs 包:express fs目的通过nodejs实现一个大文件的断点下载的服务。代码由于没啥复杂的,这里直接上代码。 http断点下载是通过range来判断文件的起始位置的。其基...【详细内容】
2021-04-27  Search: Nodejs  点击:(492)  评论:(0)  加入收藏
▌简易百科推荐
Qt与Flutter:在跨平台UI框架中哪个更受欢迎?
在跨平台UI框架领域,Qt和Flutter是两个备受瞩目的选择。它们各自具有独特的优势,也各自有着广泛的应用场景。本文将对Qt和Flutter进行详细的比较,以探讨在跨平台UI框架中哪个更...【详细内容】
2024-04-12  刘长伟    Tags:UI框架   点击:(7)  评论:(0)  加入收藏
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(11)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(23)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(61)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(51)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(41)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(58)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(71)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(94)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(91)  评论:(0)  加入收藏
站内最新
站内热门
站内头条