Nginx与LUA(7)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

您好我是湘王这是我的CSDN博客。值此新春佳节我给您拜年啦~祝您在新的一年中所求皆所愿所行皆坦途展宏“兔”有钱“兔”多喜乐常安宁


软件开发中除了进程和线程还有协程的概念。但是在搞清楚协程这个概念之前需要明白什么是进程和线程。

进程一般是应用程序的启动实例进程拥有代码和打开的文件资源、数据资源、独立的内存空间例如独立部署的jar包、运行的redis、mongodb程序等都可以成为进程。

而线程从属于进程是应用程序的实际执行者一个进程至少包含一个主线程或者有更多的子线程线程拥有自己的栈空间。

看起来在同一时刻多个线程是同时执行的也就是并发执行的但由于若干个线程对应同一个CPU所以同一个时刻其实只有一个线程是处于执行状态的。在一个时间片内执行哪个线程是不确定的只能控制线程的优先级但真正的线程调度是由CPU决定的。

般情况下各个线程都是比较独立的各自也有明确的生命周期如初始化、可运行、运行中、阻塞、销毁等不同的状态。

如果线程之间需要协作或者通信那么可以通过volatile关键字、wait/notify方法、JUC工具类或者是消息队列MQ实现。无论如何线程都会涉及到线程锁、状态切换及上下文切换。

协程是一种比线程更加轻量级的存在是「线程中的线程」。协程也拥有独立的堆栈独立的局部变量独立的指令指针同时又与其它协程共享全局变量和其它内容。

协程不被操作系统管理而是完全由线程内部控制由程序显式的进行需要多个程序彼此协作才能完成功能这就是协程名字的由来。

协程不是进程也不是线程它是通过特殊的函数来实现的——这个特殊的函数可以在某个地方「挂起」之后可以重新在其他的地方继续运行。

一个线程之内可有多个这样特殊的函数也就是有多个协程同时运行但多个协程的运行只能是「串行」的——一个协程运行时其他协程必须要挂起。同时还要明确协程也是有切换的但它的切换不是像进程或线程那样由操作系统完成而是由用户完成的所以切换效率比进程或线程高。或者可以打一个这样的比方协程类似于正在同步中的多线程而在等待同一个线程锁的几个线程也类似于协程。

协程是LUA中引入的概念由于OpenResty是对LUA的封装因此也自然就具备了协程特性。

具体来说resume和yeild是Lua协程的核心。首次调用时resume的参数会直接传递给协程函数。非首次调用时resume的另一个参数会成为yield的返回值而yield的参数也会成为resume额外的返回值。

coroutine.create(function)会传一个函数作为参数来创建协程返回coroutine当遇到resume时就唤醒函数调用。

而coroutine.yield()使正在执行的函数挂起传递给yeild的参数会作为resume的额外返回值。

先来验证coroutine.create和coroutine.resume。

修改Nginx配置文件将原来的include lua.conf改为xiecheng.conf。

vi /usr/local/openresty/nginx/conf/nginx.conf

修改xiecheng.conf内容

vi /usr/local/openresty/nginx/conf/xiecheng.conf

修改完成后重启openresty

/usr/local/openresty/nginx/sbin/nginx -s reload

访问浏览器

http://IP地址/xiecheng

可以看到三次结果都不同这其实就是resume返回值的三种情况

其他的协程方法包括

1、coroutine.isyieldable()表示如果正在运行的协程可以挂起则返回true(只有主协程(线程和C函数是无法让出的;

2、coroutine.running()用来判断当前执行的协程是不是主线程如果是就返回true;

3、coroutine.status(function)返回表示协程状态的字符串

running正在执行中的协程;

suspended还未结束却被挂起(调用了yeild或还没开始运行的协程;

normal协程A resume协程B时协程A所处的状态就是normal;

dead发生错误或正常终止的协程如果这时候对它调用resume将返回false和错误消息就像刚才展示的那样。

修改配置文件验证语法

vi /usr/local/openresty/nginx/conf/xiecheng.conf

修改完成后重启openresty

/usr/local/openresty/nginx/sbin/nginx -s reload

访问浏览器

http://IP地址/xiecheng3

协程时序图

通过以上语法可以得到几个关于OpenResty协程的知识

1、所有的协程都是通过resume和yield协作的这是协程的核心所在可以说没有resume和yield的协作就没有协程;

2、resume和yield都是由开发者控制的除此之外是不会有任何其他第三方系统干预的但线程就不一样;

3、函数从哪里挂起恢复时就从哪里开始执行关于这一点可以尝试在r1中的coroutine.yield("b")前后各加上一行ngx.print()语句来验证。

这只是Lua协程的很小一部分Lua中没有线程和异步编程的概念但对于并发执行却提供了协程的方式这确实有点奇怪。ngx_lua模块对协程做了封装可以直接通过ngx.thread API来调用。其原理就是协程A在运行中发现自己忙则把CPU使用权让出来给协程B使用最后协程A能从中断位置继续执行本地还是CPU独占的单线程。


节日期间您仍然可以随时咨询技术、产品、运营和管理相关问题请关注后留言。欢迎骚扰不胜荣幸~再次祝您兔年吉祥万事胜意

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: nginx