先明白的事儿: 当一个程序在执行的时候, 一般会创建一个进程, 也可以有多个进程. 一个进程至少会创建一个线程, 多个线程共享一个程序进程的内存. 程序的运行最终是靠线程来完成操作的. 线程的数量跟 CPU 核数有关, 一个核最多能发出两个线程.
人工智能 + 区块链的发展趋势及应用调研报告
先明白的事儿: 当一个程序在执行的时候, 一般会创建一个进程, 也可以有多个进程. 一个进程至少会创建一个线程, 多个线程共享一个程序进程的内存. 程序的运行最终是靠线程来完成操作的. 线程的数量跟 CPU 核数有关, 一个核最多能发出两个线程. 线程的操作主要分为: 一: 给 CPU 进行程序命令的执行. 二: IO 的操作 (读取或输出数据) 或者请求网络数据.
什么是阻塞: 就是线程在执行 IO 操作获取数据时, 这个 IO 可能会需要一定的时间才能等到数据返回, 然后才能接着执行下面的命令. 那么, 此时, 这个线程的等待状态我们就把它称为阻塞. 没有充分利用起 cpu 的资源.
什么是非阻塞: 还是这个线程在进行 IO 操作时, 无需等待数据的返回, 可以接着往下执行代码命令. cpu 资源一直在充分利用.
但是总要知道数据什么时候返回吧, 常见的两个解决方案:
第一: 如果程序是单线程的情况下, 在接着执行下面的代码过程中, 需要额外不断的轮询查看这个 IO 请求的数据是否返回.
第二: 使用多线程, 一个进程继续等待数据返回, 另一个线程继续操作执行下面的代码. cpu 资源一直在充分利用.
什么是同步和异步: 同步指的当线程进行 IO 操作请求数据时, 是你主动 "关心" 数据的返回. 异步是当前线程无需主动关心数据是否返回, 当数据返回时, 会有相关的事件通知你.
举个通俗的例子:
你打电话问书店老板有没有分布式系统这本书, 如果是同步通信机制, 书店老板会说, 你稍等,"我查一下", 然后开始查啊查, 等查好了 (可能是 5 秒, 也可能是一天) 告诉你结果(返回结果).
而异步通信机制, 书店老板直接告诉你我查一下啊, 查好了打电话给你, 然后直接挂电话了(不返回结果). 然后查好了, 他会主动打电话给你. 在这里老板通过 "回电" 这种方式来回调.
由此可见: 阻塞并不等于同步, 非阻塞也不等于异步. 阻塞不阻塞的区别点在于: 线程当遇到 IO 操作, 需要等待 IO 返回数据时, 是否能继续往下执行代码. 而同步与异步的区别点在于: IO 要返回的数据是需要线程主动等待, 还是被动的等待数据处理完之后主动通知你.
最好的理想方案就是: 异步非阻塞. 而 nginx 就使用的非阻塞 + 异步. apache 使用的是同步阻塞. 这也就是为什么 nginx 能比 apache 处理更多的请求更高的并发的原因.
apache 与 nginx 的工作原理:
假如下面是类似 apache 和 nginx 的伪代码:
- isten // 监听端口
- while(true){
- $conn = accept() // 一直循环接收连接
- $read_content = read(conn)// 读取请求的文件
- $esponse = process(conn) # 执行业务逻辑
- echo $espnse // 返回客户端内容
- }
- apache:
每一个连接, apache 就会创建一个进程, 每个进程内单线程, apache 最多能创建 256 个进程. 对于一个负载相对较高的网站来说, 256 的进程, 也就是 256 个线程, 因为线程处理请求时, 是同步阻塞模式, 接收请求之后, 会一直等待该请求读取程序文件 (IO)(同步), 执行业务逻辑, 返回客户端, 所有操作完成之后才能处理下一个请求(阻塞) 如果服务器已经达到 256 的极限, 那么接下去的访问就需要排队这也就是为什么某些服务器负载不高的原因了.
nginx:
nginx 接收一个请求后, 不会等待这个请求的文件读取操作完成之后才接收下一个请求, 它不会等待这个请求的后续的处理结果. 而是会马上循环处理下一个请求(不阻塞). 请求的程序文件执行完成之后, 会主动通知该线程, 不用你主动去等待或者轮询查看(异步). 最后返回给客户端. 这样做, 每个请求过来就不需要等待很长的时间排队, 而是马上就能接收, 开始进行处理了. 等处理完成之后, 会主动通知回调这个线程进行数据返回.
来源: http://server.51cto.com/Review-573603.htm