LinuxEye - Linux系统教程

LinuxEye - Linux系统教程

当前位置: 主页 > Linux教程 >

nginx和lua的协程

时间:2015-06-10 09:09来源:未知 编辑:linuxeye 点击:
1、缘起 我最早接触协程时,对这东西很费解,甚至我看了lua的协程源码实现后,这个疑虑还是没有消除。直到有次在需要用异步编程时,对协程的理解一下子明白了。所以希望用从异步
1、缘起
我最早接触协程时,对这东西很费解,甚至我看了lua的协程源码实现后,这个疑虑还是没有消除。直到有次在需要用异步编程时,对协程的理解一下子明白了。所以希望用从异步的角度解释协程,能让您有跟我一样的收获。

2、写过的
我们的业务经常需要第三方服务打交道,比如db, nosql, http api等。这种交互要么是阻塞的,要么是异步的。
在nodejs里的异步处理方式:
db.query('users', {name: name}, function(err, users) {
    deal_with(users);
});
nodejs里处理异步很简单,注册个回调即可。编程世界是多元的,每种文化都非常优秀,往往思维的碰撞会产生一些有意思的方式。我们习惯用顺序的方式写代码,如果不关心这是阻塞或是异步就很理想了,只要语言保证性能足够好。
users = db.query('users', {name: name});
deal_with(users);
可能你会认为代码会阻塞在db.query,等有结果后才会去调用deal_with。那如果加入协程的概念后呢?一切变的很有意思。

3、什么是协程?
协程是一种特殊的函数,可以在执行的过程中随时暂时,随时继续执行。这是我的理解。
function foo()
    a();
    b();
    c();
end

我们知道当我们调用foo()时,直到函数有返回或终止时才会结束执行。但是如果foo是个协程(我说过协程是一个特殊的函数)。它可以在执行到a() 时,不继续执行,先返回。等你需要时继续调用,但下次是从上次暂停的位置继续执行,也就是从b开始。这里很重要的一点是协程的暂时不是阻塞,我们会继续讲 解。所以当我们把协程引入前面的db.query例子时,如果一切如我们所希望的,它就是同步的写法,异步的实现,谁悄悄做了手脚呢?服务器和协程。

4、nginx和lua的绝配
服务器有个设计原则:永远不能阻塞。nginx作为非常优秀的服务器,这点发挥的非常极致。在nginx里有很多的体现异步的地方。我们继续以上面的例子为例:
function foo() // foo本身是个协程,由nginx调用
    users = db.query('users', {name: name}); // 此处由nginx发起db的连接请求,因为异步这里先暂停协程
    deal_with(users); // 当请求有响应得到处理时,继续执行协程,这些才运行
end

通过nginx的异步机制和lua的协程,很容易实现这种同步写法,异步实现的模型,但对开发人员而言,不用关心内部做了什么。

5、lua里如何实现协程
lua本身设计是c的胶体,除了可以写lua脚本语言代码,还可以用c调用lua的c接口。在协程这个地方也是如此。
既然上面提到nginx(c实现的),这里将列两种使用协程的方式:
a、脚本语言里使用
co = coroutine.create(function ()
    for i=1,10 do
        print("co", i)
        coroutine.yield()
    end
end)

coroutine.resume(co)   // 输出 co 1
coroutine.resume(co)   // 输出 co 2
coroutine.resume(co)   // 输出 co 3

co是个协程,是个特殊的函数
coroutine.yield是暂停(挂起)协程
coroutine.resume是继续执行(唤醒)协程

b、c调用方式
参考国内研究lua的前辈的文章:  Lua 5.2 如何实现 C 调用中的 Continuation

转载请保留固定链接: https://linuxeye.com/Linux/2610.html

------分隔线----------------------------
标签:nginxLua
栏目列表
推荐内容