Openresty Lua协程调度机制】的更多相关文章

写在前面 OpenResty(后面简称:OR)是一个基于Nginx和Lua的高性能Web平台,它内部集成大量的Lua API以及第三方模块,可以利用它快速搭建支持高并发.极具动态性和扩展性的Web应用.Web服务或动态网关. OR最大的特点就是,将Lua协程与Nginx事件驱动模型及非阻塞I/O结合起来.使用户可以在handler中使用 同步但是依然是非阻塞 的方式编写其应用代码,而无需关心底层的协程调度以及与Nginx事件驱动模型的交互. 本文将先从总体上介绍OR的协程调度机制,然后结合源码以…
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguanh/ GitHub : https://github.com/af913337456/ 腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities 前序 正确地认识 G , M , P 三者的关系,能够对协程的调度机制有更深入…
协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程. 协程是用户空间线程,操作系统其存在一无所知,所以需要用户自己去做调度,用来执行协作式多任务非常合适. 线程和协同程序的主要不同在于:在多处理器情况下,多线程程序同时运行多个线程:而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起.这样Lua的协程就不能利用现在多核技术了. (一)Cor…
参考链接: http://www.cnblogs.com/zrtqsk/p/4374360.html 对例子的自我理解: -- 协程的理解 -- co 是协程的内容,类似函数内容, 通过yield 将中止函数的操作, -- 但重新resume后,将继续执行co未执行到内容 function foo(a) print("foo", a) * a) end co = coroutine.create(function ( a, b ) print("co-body",…
注:为方便理解,本文贴出的代码部分经过了缩减或展开,与实际skynet代码可能会有所出入.    作为一个skynet actor,在启动脚本被加载的过程中,总是要调用skynet.start和skynet.dispatch的,前者在skynet-os中做一些初始化工作,设置消息的Lua回调,后者则注册针对某协议的解析回调.举个例子: local skynet = require "skynet" local function hello() skynet.ret(skynet.pac…
目录 前言 1. 线程池的缺陷 2.Goroutine 调度器 3.调度策略 3.1 队列轮转 3.2 系统调用 3.3 工作量窃取 4.GOMAXPROCS设置对性能的影响 参考 前言 Goroutine调度是一个很复杂的机制, 尽管Goy源码中提供了大量的注释,但对起原理没有一个好的理解情况下去读源码收获不是很大. 1. 线程池的缺陷 我们知道,在高并发应用中频繁创建线程会造成不必要的开销,所以有了线程池.线程池中预先保存一定数量的线程,而新任务将不再以创建线程的方式去执行,而是将任务发布到…
1 Runtime简介 Go语言是互联网时代的C,因为其语法简洁易学,对高并发拥有语言级别的亲和性.而且不同于虚拟机的方案.Go通过在编译时嵌入平台相关的系统指令可直接编译为对应平台的机器码,同时嵌入Go Runtime,在运行时实现自身的调度算法和各种并发控制方案,避免进入操作系统级别的进程/线程上下文切换,以及通过原子操作.自旋.信号量.全局哈希表.等待队列多种技术避免进入操作系统级别锁,以此来提升整体性能. Go的runtime是与用户代码一起打包在一个可执行文件中,是程序的一部分,而不是…
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Coroutine(协程) 的概念,可以帮助编写异步代码. 在使用和分析协程前,首先要了解一下: 协程是什么? 为什么需要协程? 协程最为人称道的就是可以用看起来同步的方式写出异步的代码,极大提高了代码的可读性.在实际开发中最常见的异步操作莫过于网络请求.通常我们需要通过各种回调的方式去处理网络请求,很容易就陷…
协程是个很好的东西,它能做的事情与线程相似,区别在于:协程是使用者可控的,有API给使用者来暂停和继续执行,而线程由操作系统内核控制:另 外,协程也更加轻量级.这样,在遇到某些可能阻塞的操作时,可以使用暂停协程让出CPU:而当条件满足时,可以继续执行这个协程.目前在网络服务器领域, 使用Lua协程最好的范例就是ngx_lua了,我自己的项目qnode也是借助Lua协程的概念:每一个qnode中的微进程底层对应一个Lua协程, 这样底层的异步操作可以在使用者使用同步的方式写出来.Coool. 来看…
LUA协程和C#协程非常相似,功能与用法更强大.基础用法: coco = coroutine.create(function (a,b) print("resume args:"..a..","..b) , , ) --第一次调用resume()时执行到此句就返回了,没有执行=赋值操作 --第二次执行resume()操作时,从=号开始继续执行剩余代码,且此时新的调用参数(21,11111)从=号传出给了arg1, arg2 --除了=号传参这一点外,其余都基本与c#…
一.线程模型 N:1模型,N个用户空间线程在1个内核空间线程上运行.优势是上下文切换非常快但是无法利用多核系统的优点. 1:1模型,1个内核空间线程运行一个用户空间线程.这种充分利用了多核系统的优势但是上下文切换非常慢,因为每一次调度都会在用户态和内核态之间切换.(POSIX线程模型(pthread),Java) M:N模型, 每个用户线程对应多个内核空间线程,同时也可以一个内核空间线程对应多个用户空间线程.Go打算采用这种模型,使用任意个内核模型管理任意个goroutine.这样结合了以上两种…
print("Lua 协程测试3") -- 实现消费者-生产者关系(生产一个就消费一个) count = -- 生产总数 -- 生产者 local newProductorCo = coroutine.create( --创建协程 function() local i = while(i <= count)do coroutine.yield(i) -- 挂起协程 i = i + end end) -- 消费者 ,count do local status,value = cor…
print("Lua 协程测试2") function testFun(n) print("into foo,n = "..n) * n) -- 挂起co协程 end co = coroutine.create( -- 创建co协程 function(a,b) print("into co 1,a = "..a..",b = "..b) local r = testFun(a) print("into co 2,r…
协程是个很好的东西,它能做的事情与线程相似,区别在于:协程是使用者可控的,有API给使用者来暂停和继续执行,而线程由操作系统内核控制:另外,协程也更加轻量级.这样,在遇到某些可能阻塞的操作时,可以使用暂停协程让出CPU:而当条件满足时,可以继续执行这个协程.目前在网络服务器领域,使用Lua协程最好的范例就是ngx_lua了 来看看Lua协程内部是如何实现的. 本质上,每个Lua协程其实也是对应一个LuaState指针,所以其实它内部也是一个完整的Lua虚拟机-有完整的Lua堆栈结构,函数调用栈等…
一个大胆的尝试:使用巨型lua协程来表示整个“一局”流程. lua协程是一个很另类的功能,有并发的影子但又不是真的并发,所以真正拿它来做大功能框架的范例不多,通常用于一些小型trick式设计.但这次我在大富翁里把它用到了“极致”:整个一局游戏,就是全部跑在一个协程里的! 简单的说:在开始按钮的点击响应函数里(自然是在“主协程”中),创建出用于新一局游戏的“run协程”,然后在这里面启动这一局的while大循环,共3层:第1层为每个回合,第2层为每个玩家,第3层为每个指令.每当要等待一个指令时,r…
阅读本文仅需五分钟,golang协程调度原理,小白也能看懂,超实用. 什么是协程 对于进程.线程,都是有内核进行调度,有CPU时间片的概念,进行抢占式调度.协程,又称微线程,纤程.英文名Coroutine.协程的调用有点类似子程序,如程序A调用了子程序B,子程序B调用了子程序C,当子程序C结束了返回子程序B继续执行之后的逻辑,当子程序B运行结束了返回程序A,直到程序A运行结束.但是和子程序相比,协程有挂起的概念,协程可以挂起跳转执行其他协程,合适的时机再跳转回来. 线程调度原理 N:1模型,多个…
协程就是协程,不是线程. CPU执行单位是线程,不是什么协程. 协程,是同步执行,不是并行,只是切了一个上下文了,为你保存原来的上下文而已. 切到第二个协程时,原来的协程处于挂起状态. 这个特指lua的协程. Unity的协程也是这么回事. lua协程例子: local function run(data) print("co-body", 1, data.a) print("co-body", 2, data.a) print("co-body"…
下载8个1m大小文件,测试五次分别耗时12.038s,10.316s,8.955s,11.275s,9.499s(lua代码实现如下) require "socket" --host = "www.w3.org" --file = "/TR/REC-html32.html" function lua_string_split(str, split_char) --字符串拆分 local sub_str_tab = {}; while (true…
我们的游戏有这样一种情景:客户端中角色需要用到一些公会的数据,但服务器不会在玩家(创角后)一进入到游戏里就推送给玩家,而是需要客户端自己在需要的时候向服务器请求公会的数据,之前的实现就是在请求消息的时候加一个回调函数,消息一回来就执行回调函数继续后续的业务!但后面发现存在这样的不足: 1.有时会用到好多个参数,这就需要每次都把一些无关的参数传给消息请求者,然后回调过来再把这些参数原封不动地传回来,很繁琐: 2.这样的回调写法感觉很不符合人类的顺序思维习惯,有点乱: 回调的lua代码写法类似: -…
现在无论是客户端.服务端或web开发都会涉及到多线程的概念.那么大家也知道,线程是操作系统能够进行运算调度的最小单位,同一个进程中的多个线程都共享这个进程的全部系统资源. 线程 三个基本概念 内核线程:在内核空间实现的线程,由内核管理 用户线程:在用户空间实现的线程,不归内核管理,由用户态完成管理 轻量级进程(LWP):在内核中支持用户线程(用户线程与内核线程的中间层,内核线程的高度抽象) 线程模型 一对一模型(内核级线程模型) 由进程创建LWP,由于每个LWP对应一个内核级线程,所以用户也就是…
协程,简单来说就是新创建一个协助程序(co = coroutine.create(func)),然后需要手动去启动它(coroutine.resume(co)),在它最终退出之前,它有可能暂停多次返回阶段性的结果(coroutine.yield(co)),每一次暂停之后都必须手动去恢复它(coroutine.resume(co)). 协程在lua源文件中对应lcorolib.c,数组co_funcs中定义了c暴露给lua的接口.从上面的描述看和c函数调用有点相似,只不过c函数只有一个出口,所以不…
--[[ - @desc lua数据输出 - @param string 字符串 - return string --]] function dump(v) if not __dump then function __dump(v, t, p) local k = p or ""; if type(v) ~= "table" then table.insert(t, k .. " : " .. tostring(v)); else for key…
协同程序线程类和多线程下似:它有它自己的堆栈.自己的局部变量.它有自己的指令指针,但是,其他协程共享全局变量和其他项目信息.主要不同在于:多处理器的情况下.概念上来说多线程是同一时候执行多个线程,而协程是通过协作来完毕,不论什么时刻仅仅有一个协程程序在执行.而且这个在执行的协程仅仅有明白被要求挂起时才会被挂起 你能够使用coroutine.create来创建协程: co = coroutine.create(function ()      print("hi") end) 协程有三种…
很久没记录笔记了,还是养成不了记录的习惯 下面是来自 programming in lua的一个协程的例(生产者与用户的例子) 帖代码,慢慢理解 -- Programming in Lua Coroutine(协程)--[[coroutine.createcoroutine.resumecoroutine.runningcoroutine.statuscoroutine.wrapcoroutine.yield--]] --管道和过滤 --生产者与用户的例子 --[[***************…
-----协程复用根函数 local function routine(fun, args) while (fun) do fun, args = coroutine.yield(fun(table.unpack(args))); end end -----demo 1 : 使用一个协程,用来调用不同的參数和不同的函数 local Sum = function(...) local sum = 0; for i=1, select("#", ...) do sum = sum + se…
Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间的通信, 它的宗旨是: Do not communicate by sharing memory; instead, share memory by communicating. Channel basics channels用于协程间的通信, 允许我们在不同的协程间传递数据(a stream of…
goroutine与线程 /* goroutine与线程1. 可增长的栈os线程一般都有固定的栈内存,通常为2MB,一个goroutine的在其声明周期开始时只有很小的栈(2KB),goroutine的栈是不固定的,它可以按需增大或缩小,goroutine的栈大小限制可以达到1GB,虽然极少会用到这么大,所以在go语言中一次创建十万左右的goroutine也是可以的2. goroutine的调度GPM是go语言运行时(runtime)层面的实现,是go语言自己实现的一套调度系统,区别于操作系统调…
协作例程 1.同一时刻仅一个例程在运行 2.执行权让渡和恢复[栈]…
按照书上码了下,但运行有问题,暂时不知道原因: function send (x) coroutine.yield(x) end function producer() return coroutine.create( function () while true do local x = 1 send(x) end end) end function receive(prod) local status, value = coroutine.resume(prod) return value…
前面一篇文章介绍了Openresty Lua协程调度机制,主要关心的是核心调度函数run_thread()内部发生的事情,而对于外部的事情我们并没有涉及.本篇作为其姊妹篇,准备补上剩余的部分.本篇将通过一个例子,完整介绍OpenResty中Lua钩子的调用流程,包括初始化阶段的工作.新连接进来时如何进入钩子.I/O等待时如何出去.事件触发时如何恢复.钩子正常执行结束时的操作.钩子内出错的情况.本文同样是基于stream-lua模块的代码. 本博客已经迁移至CatBro's Blog,那里是我自己…