像我五岁一样讲解非阻塞I / O

Introduction

十年前,网络应用程序开发领域发生了重大变化。 2009年,Ryan Dahl发明了Node.js,因为他对流行的Apache HTTP Server处理成千上万的并发连接的可能性感到不满意。 Node.js项目结合了JavaScript引擎,事件循环和I / O层。 通常将其称为非阻塞Web服务器。

The idea of non-blocking I/O in combination with an event loop is not new. The Java community added the NIO module to J2SE 1.4 already back in 2002. Netty, a non-blocking I/O client-server framework for the development of Java network applications, is actively developed since 2004. Operating systems are offering functionality to get notified as soon as a socket is readable or writable even since before that.

如今,您经常听到或阅读诸如“ X是一种无阻塞,事件驱动,可扩展的[在此处插入另一个流行语]框架”之类的注释。 但是它是什么意思,为什么有用呢? 这篇文章的其余部分结构如下。 下一节将以简单的类比说明非阻塞I / O的概念。 随后,我们将讨论非阻塞I / O的优缺点。 下一部分将使我们了解如何在不同的操作系统中实现非阻塞I / O。 我们将通过给出一些最后的想法来结束这篇文章。

Your Own Table Factory

Your First Employee and Work Bench

想象一下,您正在建立一家生产桌子的公司。 您正在租一栋小建筑物并购买一个工作台,因为您只有一个员工,我们称他为乔治。 早上,乔治进入大楼,进入工作台,然后从收件箱中接一个新订单。

桌子的大小和颜色各不相同。 储藏室中有相应的资源和用品。 但是有时储藏室没有所需的材料,例如 缺少颜色,所以乔治不得不订购新的耗材。 因为乔治喜欢先完成一件事,然后再开始另一件事,所以他只需要在工作台上等待,直到新的耗材交付为止。

以此类推,工厂代表一个计算机系统,工作台代表您的CPU,而George是一个工作线程。 订购新的耗材对应于I / O操作,您可以将其视为协调所有交互的操作系统。 CPU没有多任务处理功能,每个操作不仅阻塞线程,而且阻塞整个CPU,进而阻塞整个计算机。

Multiple Employees, Single Workbench

您想知道是否可以通过说服乔治在交付用品时进行其他工作来提高生产率。 可能要过几天才能收到新货,乔治会站在那儿什么也没做。 您面对着他的新计划,但他回答:“老板,我真的很难适应上下文切换。但是我很乐意回家,在那里什么也不做,所以我至少不会阻塞工作台!”。

您意识到这不是您希望的,但是至少您可以在George在家等待交付时雇用另一名员工在板凳上工作。 您正在雇用Gina,而George在家时她正在组装另一张桌子。 有时,乔治必须等待吉娜(Gina)整理桌子,然后才能继续工作,但生产率却几乎翻了一番,因为乔治的等待时间得到了更好的利用。

通过让多个员工共享同一工作台,我们引入了一种多任务处理形式。 有多种不同的多任务处理技术,这里我们有一个非常基本的技术:一旦一个线程被阻塞,等待I / O,就可以将其停放,另一个线程可以使用CPU。 但是,在I / O繁重的应用程序中,这种方法需要我们雇用更多的员工(产生更多的线程)来等待。 雇用工人很昂贵。 还有其他提高生产率的方法吗?

Multitasking, Non-Blocking Employees

在她的第二个星期,吉娜(Gina)也用完了。 她意识到在等待交货时仅在另一张桌子上工作实际上并不坏,因此她要求您在交货到达时向她发送一条短信,以便她可以在完成当前工作后继续在那张桌子上工作 或正在等待其他交货。

现在,吉娜(Gina)正在使用9到5的工作台,乔治意识到她的生产力要比他高。 他决定换工作,但幸运的是,吉娜(Gina)有一个和她一样灵活的朋友,而且由于您出售了所有桌子,您可以负担得起第二个工作台。 现在,每个工作台都有一名员工全天工作,利用等待时间来等待供应货物,同时处理另一个订单。 多亏了您关于已到达交货的通知,他们可以专注于工作,而不必定期检查交货状态。

在等待交货时将工作模式更改为不再空闲之后,您的员工将以非阻塞方式执行I / O。 尽管George在开始等待在家交付后也不再阻塞CPU,但他仍在等待并因此阻塞。 吉娜(Gina)和她的朋友只是在做其他事情,挂起需要交付耗材的桌子的组装,等待操作系统向他们发出I / O结果准备就绪的信号。

Benefits of Non-Blocking I/O

我希望以前的类比可以弄清楚非阻塞I / O的基本思想是什么。 但是什么时候有用? 通常,人们可以说,一旦您的工作负载受I / O约束,就可以立即受益。 例如,这意味着您的CPU将花费大量时间等待您的网络接口。

Using non-blocking I/O in the right situation will improve throughput, latency, and/or responsiveness of your application. It also allows you to work with a single thread, potentially getting rid of synchronization between threads and all the problems associated with it. Node.js is single-threaded, yet can handle millions of connections with a couple of GB RAM without problems.

A common misconception lies in the fact that non-blocking I/O means fast I/O. Just because your I/O is not blocking your thread it does not get executed faster. As usual there is no silver bullet but only trade-offs. There is a nice blog post on TheTechSolo discussing advantages and disadvantages of different concepts around this topic.

Implementations

There are many different forms and implementations of non-blocking I/O. However all major operation systems have built-in kernel functions that can be used to perform non-blocking I/O. epoll is commonly used on Linux systems and it was inspired by kqueue (research paper) which is available in BSD based systems (e.g. Mac OS X).

使用Java时,开发人员可以依赖Java NIO。 在大多数JVM实现中,如果适用,可以期望Java NIO使用那些内核函数。 但是,在细节上有一些微妙之处。 由于Java NIO API具有足够的通用性,可以在所有操作系统上工作,因此它无法利用某些单独实现的高级功能投票要么que提供。 它类似于非常基本的轮询语义。

Thus if you are looking for a little bit of extra flexibility or performance you might want to switch to native transports directly. Netty, one of the best network application framework on the JVM, supports both Java NIO transports as well as native libraries for Linux and Mac OS X.

Of course most of the time you are not going to work with Java NIO or Netty directly but use some web application framework. Some frameworks will allow you to configure your network layer to some extend. In Vert.x, for example, you can choose whether you want to use native transports if applicable and it offers

Final Thoughts

术语“非阻塞”以许多不同的方式和上下文使用。 在本文中,我们专注于非阻塞I / O,它是指不等待I / O操作完成的线程。 但是,有时人们将API称为非阻塞API只是因为他们没有阻塞当前线程。 但这并不一定意味着它们执行非阻塞I / O。

Take JDBC as an example. JDBC is blocking by definition. However there is a JDBC client out there which has an asynchronous API. Does it block your thread while waiting for the response of the database? No! But as I mentioned earlier, JDBC is blocking by definition so who is blocking? The trick here is simply to have a second thread pool that will take the JDBC requests and block instead of your main thread.

为什么有帮助? 它可以让您继续进行主要工作,例如 回答HTTP请求。 如果不是每个请求都需要JDBC连接,那么在线程池被阻塞时,您仍然可以使用主线程来回答这些请求。 这很好,但仍会阻塞I / O,一旦您的工作受到JDBC通信的束缚,您将遇到瓶颈。

该领域非常广泛,还有更多细节需要探索。 但是,我相信,对阻塞与非阻塞I / O有了基本的了解,当遇到性能问题时,您应该能够提出正确的问题。 您曾经在应用程序中使用本机传输吗? 您之所以这样做,是因为您可以解决还是因为性能问题而困扰? 在评论中让我知道!


Cover image by Paul Englefield

from: https://dev.to//frosnerd/explain-non-blocking-i-o-like-i-m-five-2a5f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值