同步&异步

堵塞&非堵塞

什么同步?



发起任务并等待其结束,再获取结果


优点:代码逻辑简单
缺点:空跑,占用资源并傻傻的等着

PHP


分2个部分:
  1. Nginx+PHPFPM

    Nginx里面是异步逻辑

  2. PHP+MySQL...

    PHP里面是同步逻辑

    echo('start');
    $res = mysql_query('SELECT * FROM t');
    echo('done');

什么是异步?



发起任务,做其他事情,接收任务结果


优点:同样的时间做更多的事情
缺点:代码逻辑较复杂

NODE.JS


纯异步逻辑

var ok = db.query('SELECT * FROM t', 
    function(res){
        console.log('done');
});

console.log('start');

矛盾



我们都希望代码逻辑更简单、清晰

但我们还追求性能!




只有异步逻辑才能使用非堵塞IO?

NO



IO是否堵塞跟同步、异步逻辑无关!


只要发起多个同步逻辑,那么对于整体来说也是异步架构



支持非堵塞IO,要做的就是如何获取到结果

可采用的方式有3种

  1. 异步逻辑 callback 回调通知(代码逻辑复杂,比较常见)
  2. 多线程或协程的同步逻辑等待结果(代码简单,常见)
  3. 定时检查结果(有消耗,且不即时,少见)




又回到同异步逻辑的问题上


何为同步?何为异步?


Nginx + PHPFPM 是异步,每个PHP进程里面是同步的
多进程是异步,但每个线程里面是同步的


也就是说同步与异步只是对某个业务整体架构的描述


只要整体架构是异步的即可使用非堵塞IO

你可以使用多线程或者多协程


进程 > 线程 > 协程

要注意协程的开销比线程小得多,切换效率更高

所以!



为了代码逻辑清晰,我们选择同步逻辑

而为了性能我们选择·协程·


在业务中发起多个协程并行工作
业务整体是异步架构的

架构模型


Main Thread { //一般都是epoll/kqueue的事件循环
    //async
    sub thread 1(...sync...) //子业务的同步代码逻辑
    sub thread 2(...sync...)
    sub thread 3(...sync...)
    ...
    sub thread n(...sync...)
}

支持多线程或协程的语言


  • PHP        不支持
    (Yar/
    Swoole扩展支持回调型异步逻辑)
  • Java         支持
  • Nodejs  支持
  • Python  支持
  • Lua           支持
  • Go            支持
  • C               支持

基于协程使用非堵塞IO






程序主逻辑以epoll/kqueue事件驱动


当收到IO事件通知时对协程进行调度,如:

  • Accept 接收到请求,创建协程处理请求业务
    协程业务中发起read或write操作,并进入 yield 睡眠状态

  • Read/Write 接收到可读写事件,把结果返回给协程
    并切换协程状态至 running


aLiLua 是一个基于epoll/kqueue驱动的 Web Server

其他

OpenResty | Tornado | ...


非常感谢 OpenResty 项目,@章亦春
aLiLua 项目中的MySQL/Redis/Memcache客户端均来自于OpenResty :)



Q&A

同步&异步

By oneoo huang

同步&异步

  • 719