作为一名程序员,相信大家在软件架构图上经常见到 “Nginx + Lua” 的字样,但是对于Lua在Web应用中的作用并没有多少了解。
该篇文章对 Lua 的语言特性、优势等方面做介绍,并通过介绍一个天气预报的 Web 应用,让大家对 Lua 在Web应用中充当的角色有一个直观的认识。
什么是 Lua
Lua 是用标准C语言编写的一种小巧的脚本语言,并以源代码形式开放。Lua 并没有提供强大的库,所以我们很少单独使用 Lua 去编写程序,其设计目的是为了嵌入其他应用程序中,比如嵌入 Cocos2d-x 游戏引擎或 Nginx 服务器,从而为应用程序提供灵活的扩展和定制功能。
Lua 的语言特性
Lua 的语法并不复杂,易于上手,而且网上已有大量的语法教程,所以该篇文章不再赘叙,这里介绍几个 Lua 语言相对重要的语言特性。
-
协程并发
协程相对独立,有自己的上下文,但是其切换由程序自己控制(线程的切换是由操作系统控制,这是协程与线程的重要区别)。
Lua 的协程通过扩展库 coroutine 来实现,通过 create 函数创建一个协程,resume 函数以运行此协程,直到新协程调用 yield 函数,程序才能返回到“主协程”中运行。
在 Java 程序中,我们常常使用回调函数来实现异步调用,但是如果在回调函数中又嵌套回调函数,这样的代码结构并不直观。而 Lua 的协程,封装了底层的回调代码,让我们可以用同步调用的方式编程,实现异步调用的功能。
-
自动内存管理
Lua 中所有用到的内存,如:字符串、表、用户数据、函数、线程、内部结构等,都服从自动管理,其垃圾回收算法是标记清除垃圾收集算法。
-
闭包
闭包是指将一个函数写在另一个函数之内,这个位于内部的函数可以访问外部函数中的局部变量。Lua 的语言特性支持闭包的功能。通过使用闭包,我们可以实现函数式编程,类似 Java 8 的 Lambda 表达式。
Lua 的优势
-
可扩展性
Lua 由C语言编写,Lua 和 C/C++ 之间可以相互调用,从而可以在 Lua 中嵌入大量的功能。
-
小巧快速
一个完整的 Lua 解释器不过200k,在目前所有脚本引擎中,Lua 的速度是最快的。而且其小巧的特性,不会给宿主程序带来性能上的影响。这决定了 Lua是作为嵌入式脚本的最佳选择。
-
热更新
Lua 的热更新特性是其被运用在游戏服务器的重要因素。热更新能够在服务器运行期间更新程序逻辑代码以实现修正程序Bug,减少服务器的重启造成经济上的损失。
-
LuaJIT
LuaJIT 即Lua Just-In-Time Compiler,不同于官方的Lua编译器,使用LuaJIT可以实现一次编译多次运行,其执行速度比使用官方的 Lua 解释器快。
Lua 的应用场景
Lua 因为其快速、可扩展的优势,被广泛应用于多个方面,其中主要的两个方面是游戏开发和 Web 应用脚本。
1. 游戏开发(Cocos2d-x + Lua + C++)
Lua 大量被用于游戏开发,主要是搭配Cocos2d-x ,作为脚本来处理从逻辑到UI的各种工作,如:《愤怒的小鸟》、《魔兽世界》。单纯使用C++开发的成本比较高,而使用C++提供各种基本的功能函数库,Lua调用这些库来实现各种逻辑功能,可以实现基本代码库和逻辑代码分离,减低编程成本。
2. Web 应用脚本(Nginx + Lua)
Lua 的另一个常见应用场景是编写 Nginx 服务器的脚本。一开始开发者都使用C/C++ 做Nginx 开发,但是使用 C/C++ 开发 Nginx的程序对开发者的要求较高,开发者需要了解 Nginx 的工作原理和内部处理流程,熟悉各种数据结构,掌握进程、事件等运行机制,开发成本高,周期长。直到Openresty(一个基于Nginx与Lua的高性能Web平台,下文会做介绍)的诞生,该平台集成大量的 Nginx 功能模块和Lua模块,开发者可以用 Lua 作为“胶水语言“粘合 Nginx 的各个模块和底层接口,以脚本的方式实现业务逻辑。
Nginx 的介绍
接下来将为大家介绍一个使用 Lua 作为脚本的 Web 应用,由于该程序搭建于 Nginx 服务器之上,所以在介绍该程序之前,需要先介绍 Nginx 服务器。
Nginx是一款轻量级的Web 服务器和反向代理服务器,其特点是占有内存少,单线程、异步非阻塞处理请求,并发能力强。
图示为 Nginx 的进程结构图,Nginx设计为一个主进程多个工作进程的工作模式,每个进程是单线程来处理多个连接,而且每个工作进程采用了单线程非阻塞I/O来处理多个连接,从而减少了线程上下文切换,从而实现高性能、高并发。
OpenResty 的介绍
如果使用 C++ 开发 基于Nginx 的 Web应用,开发者需要了解 Nginx 的工作原理和内部处理流程,开发成本高,周期长。本部分介绍 OpenResty,在该平台上可以方便地开发基于 Nginx 的应用程序。
OpenResty 的官方介绍:“OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。”
图示为OpenResty 的组成结构图,核心是 Nginx 服务器,Ngx_lua 模块在 Nginx 中嵌入 LuaJIT 即时编译器,因此开发者可以使用 Lua 脚本调用各种 Nginx 模块(Ngx_echo)和 Lua 模块(Lua_redis,Lua_cjson),快速开发Web程序。
应用一:天气预报 API
本部分带大家动手搭建一个简单的Web应用。该Web应用基于OpenResty(Nginx+Lua),在第三方天气预报 API 的基础上做一层简单的封装,实现自定义的天气预报 API 的功能。
程序的结构比较简单,请求到达 Nginx 服务器,然后 Lua 脚本做简单的逻辑处理,并通过 Nginx 正向代理到第三方的天气预报 API 服务器上,最后响应请求。
程序的源代码可以在本人的 GitHub 下载,地址为:
https://github.com/zhenghangjin/Openresty-Weather-API
应用二:Lua 实现限流和负载均衡
Lua 除了可以在 Web 程序中做逻辑处理,还可以用来扩展 Nginx 的配置,Lua 提供了比 Nginx 默认配置规则更加灵活的设置方式。
比如开发者可以使用 Lua 编写限流算法,如:令牌桶算法、漏桶算法或其他自定义的算法;还可以使用 Lua 编写负载均衡算法。
Nginx + Lua 的使用建议
Nginx + Lua 并不适合开发业务逻辑复杂的 Web 应用,我们可以通过 Nginx 的并发模型和Lua 的语法特性两个方面来分析。
-
Nginx 的并发模型
Nginx每个进程以单线程、异步非阻塞的方式处理请求。当某个请求做I/O处理时,所在的进程可以处理其他请求,提高CPU的利用率,响应速度快,适用于开发I/O密集型应用和业务逻辑单一的应用。
-
Lua 的语法特性
另一方面,Lua 的语言特性比较简单,没有类似 Java 语言的封装、继承、多态等特性,如果应用程序的业务逻辑比较复杂,代码无法很好地重构,不利于维护。
总结
最后,对这次 Lua 的学习之旅做一个总结。 Lua 是一门优秀的脚本语言,其快速、小巧、可扩展的特性深受开发者所喜爱。但是 Lua 在Web应用领域的书籍和博客还是比较少,希望有更多的开发者投入到 Lua 的学习之中,为打造一个良好的 Lua 生态圈贡献出自己的一份力量。
转载请并标注: “本文转载自 linkedkeeper.com (文/张松然)”