【Nginx】阻塞非阻塞与同步异步

1.概念理解

这里讨论的阻塞和非阻塞是函数(java里叫方法)的属性上来说;
这里讨论的同步和异步是从调用函数(方法)的方式上来说.
同步:协同步调,按预定的先后次序进行.


1.阻塞方法:操作系统或者底层的C库提供的方法或者一个系统调用可能会(当前的条件不满足)导致进程sleep状态,操作系统运行此
进程的CPU切换成去执行其他进程,这样的方法称作阻塞方法.
2.非阻塞方法:操作系统或者底层的C库提供的方法或者一个系统调用永远不会因为除了时间片到了的情况而被操作系统将执行当前进
程的CPU切换去执行其他进程,这样的方法称作非阻塞方法.
3.同步调用方式:同步调用表明调用一旦开始,调用者必须等待方法执行完成,才能继续执行后续方法.
4.异步调用方式:异步方法表明,方法一旦开始,立即返回,调用者无需等待其中方法执行完成,就可以继续执行后续方法.

 Nginx现在利用javascipt利用同步写代码的方式实现非阻塞编码的效果,
 Openresty基于Lua语言利用同步写代码的方式实现非阻塞高并发的效果.

可以思考一下几种组合:
以同步的方式调用阻塞方法;
以同步的方式调用非阻塞方法;
以异步的方法调用阻塞方法;
以异步的方法调用非阻塞方法.

2.accept举例

accept为例:

阻塞调用:
一些程序使用accept的时候都是用阻塞socket的,使用阻塞socket的时候,
在我们调用accept方法的时候,如果我们监听的端口所对应的accept队列(已经做好三次握手的就绪队列)
不为空,那么阻塞方法可能立刻返回而不会被阻塞,但是accept队列如果是空的,
操作系统就会等待新的三次握手的连接到达我们的内核中,我们才会唤醒accept
调用,这个时间往往是可控的,我们可以设置这个阻塞socket最长的超时时间,
如果没有达到的话,也可以唤醒我们的调用.这里的流程中就会出现进程间的主动切换的
现象出现.但是我们Nginx是不能容忍这种进程间的主动切换的,因为它的并发连接数太多了.


非阻塞调用:
利用fcntl将socket设置成非阻塞属性的,当这时调用accept的时候,如果accept队列
为空,这时是不等待立刻返回的,我们此时调用的accept函数会返回一个特殊的EAGAIN
错误码,我们需要对这个错误码进行特殊处理.
如果我们再次调用accept,此时如果accept队列不为空,则将套接字从accept队列中
拷贝出来给进程,然后处理套接字.
这里有一个问题,这里由代码决定当accpect返回EAGAIN的时候,究竟是等一会继续处理
这个连接(比如说sleep一下),还是切换到任务再处理.

异步的方式去调用非阻塞函数是非常自然而然的.

 

 

3.非阻塞调用下的同步和异步

Nginx反向代理例子中

标准异步调用实现非阻塞功能:
Nginx在做反向代理的时候,会去考虑到上游服务的处理能力是相对不足的,所以如果是一个有
body的http请求,Nginx会先把body接受完,再去向上游服务器发起连接.看代码可以发现,
当我们收完header的时候,我们已经知道该向哪一台上游服务器发起反向代理建立连接,但是
我们这里先调用了读取body的方法,这个方法就是一个标准的异步调用的方法,表达:
当执行完ngx_http_read_request_body以后,再去回调post_handler的方法,也就是说
ngx_http_upstream_init是我们对上游服务器建立连接的方法,当我们调用这个异步调用的
时候意味着现将ngx_http_read_request_body,再调用ngx_http_upstream_init方法,
这个非常复杂,难以理解(哈哈,还是挺好理解的).


openresty使用了同步调用实现非阻塞功能:
比如现在要对redis建立连接,new一个redis的对象且设置好超时时间,连接redis需要
三次握手建立连接,在Nginx中,绝对是不允许使用阻塞方法的,使用异步方式非常复杂,
于是这里用了同步方式来实现异步的效果:
这里的connect是一个同步调用,但是它里面走的是非阻塞方法,所谓我们在写lua代码
的时候完全不用考虑connect完成以后再去回调另外一个方法,在另外一个方法中去决定
connect成功了还是失败了,如果成功了,应该发消息.这里完全不需要这么做,我们只
只需要简单地connect,收到响应值以后判断是否OK,不OK打印错误.
因为redis::connect方法内部自己是一个非阻塞模式:
当redis::connect内部的connect没有被满足的时候,即没有收到成功建立了连接的响应
的时候,connect方法不会返回也不会阻塞Nginx的代码,这就是同步调用代码实现非阻
塞的效果.




 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值