美文网首页
Nginx异步非阻塞

Nginx异步非阻塞

作者: 全栈小运维 | 来源:发表于2020-03-27 15:37 被阅读0次

    在使用socket编程中,经常会看到阻塞、非阻塞、同步、异步,那么它们之间到底有什么关系跟区别呢?
    本次将那Nginx的异步非阻塞的事件驱动模型来解释一下它们之间的关系。

    阻塞IO

    在linux中,默认所有socket都是阻塞的。

    这意味着使用该socket调用诸如recv的函数时,在没有数据到达之前,该函数将不会返回,导致线程被阻塞,直到数据到达。

    非阻塞IO

    我们可以使用fcntl把socket设置为非阻塞的。

    这意味着使用该socket调用诸如recv的函数时,该函数将立刻返回,可以根据返回值来确定是否有数据到达。

    相信阻塞/非阻塞IO的大家都非常的清楚,本次主要说的是同步IO跟异步IO之间的区别。

    首先要说的是,同步/异步只是跟具体实现有关,就是说非阻塞的必定是异步的的说法是错误的,它们之间并没有确定的关系。

    同步IO

    一般来说,我们调用的函数都是同步的。

    何为同步呢?就是说我们调用了一个函数,在该函数返回之后就说明该函数要做的东西已经完成了。

    这是我们一般的做法,例如说我们调用recv接收数据,在该函数返回之后,就代表我们已经接收好数据了。

    异步IO

    异步IO大概可以这样理解:

    我们调用一个函数,在该函数返回之后其实该函数要完成的事情还没真正完成,而是被托管到其它地方了(如Nginx的事件驱动)。

    可见该函数的功能并不是立刻完成的(但是最终会由托管的模块去完成)。

    可能读者会有这样的疑问:异步IO到底是怎么样实现的呢?它有什么应用呢?下面将拿Nginx的事件驱动模型来解决这些问题。

    异步非阻塞IO的应用

    拿一个比较容易理解的例子:

    在处理HTTP请求的时候,如果要忽略请求包体的内容(我们必须接收包体,但是不做处理),我们会ngx_discard_reqeust_body函数。

    忽略请求包体的过程可能比较长,但是我们不需要理会包体的内容(该函数返回的内容我们并不在意),因此该函数是异步非阻塞的:

    这样,在调用该函数之后我们可以继续执行下面的代码,而接收并忽略包体的动作则托管给事件驱动去完成。

    异步非阻塞IO在Nginx的实现

    Nginx的高并发来源于其异步非阻塞的事件驱动,下面将对Nginx基于epoll的事件驱动模型来说明。

    关于epoll的使用方法跟Nginx事件驱动模型可以查看文章的前面两部分,这里将不做详细说明。

    可见,Nginx主循环会调用ngx_epoll_process_events方法,而该方法则调用epoll_wait来获取事件并且处理事件。

    我们只要调用epoll_ctl向epoll中添加或者删除事件(托管事件),Nginx事件驱动就会帮我们在事件准备好的时候处理相应的事件了。

    相关文章

      网友评论

          本文标题:Nginx异步非阻塞

          本文链接:https://www.haomeiwen.com/subject/oygluhtx.html