Kong网关:入门、实战与进阶
上QQ阅读APP看书,第一时间看更新

3.1 Lua入门与规范

Lua是一门小巧的脚本语言,于1993年在巴西里约热内卢天主教大学诞生。从发布至今,Lua语言几经沉浮。下面我们一起走进Lua语言的世界。在本节中,笔者会带领读者一起了解Lua语言的基础知识、安装流程、解释器原理及一些常用的使用规范。

3.1.1 基础知识

Lua根据标准C编写而成,几乎在所有操作系统和平台上都可以编译、运行。Lua虽小,但五脏俱全。其源码包大小仅有200KB,却拥有一组精简且强大的特性,以及易使用的C API,这使得它非常容易嵌入其他应用程序,从而提供灵活、丰富的扩展和定制功能。然而,Lua语言并没有提供强大的功能库,所以它无法形成完整的技术生态。当然,这是由它的定位所决定的。因此,Lua语言不太适合用来独立开发应用程序。

除此之外,Lua还有一个同期进行的LuaJIT项目,即Just-In-Time,也就是运行时编译器。LuaJIT的语法和标准Lua的语法类似,但是其运行速度比标准Lua快数十倍,可以说是Lua的一个高效率版本。

Lua因为其语言特点,常用于游戏脚本引擎,如《魔兽世界》《愤怒的小鸟》。Lua与Nginx生态环境也结合得非常紧密。Lua语言大量用于OpenResty和Kong插件中。总体而言,Lua语言是C\C++的“王牌搭档”。C\C++应用程序与Lua语言结合完美地平衡了性能和灵活性,这也正是Kong网关能够提供高性能和高度定制化插件的基础。

注意

Lua是作为一门胶水语言出现的。区别于C、Java或者Python等生态语言,它没有自己独立的环境,必须依附在宿主语言环境中才能起作用。所以说从一开始,Lua就非常明确自己的定位:它不想自己做大,而是想做得足够精简、小巧,嵌入宿主语言,以提供一些动态特性。除Lua之外,常用的胶水语言还有Shell脚本、TCL语言等。

3.1.2 安装指南

下面我们一起来安装Lua。与之前几章类似,笔者提供三种不同场景下的安装方法。读者根据自己开发环境选择安装。

1.在Mac环境中安装Lua

在Mac环境中,我们还是选用Homebrew工具安装。安装过程如下所示:


# 安装Homebrew,如果已经安装请忽略
$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"  
# 安装Lua
$ brew install lua
# 验证是否安装成功
$ lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

当系统提示Lua 5.3.5 Copyright(C)1994-2018 Lua.org,PUC-Rio信息,表示Lua环境已经安装成功。

2.在Linux环境中安装Lua

大多数Linux系统已经预装Lua程序,一般情况下可以直接使用,但建议读者检查一下预装Lua的版本,以防中途因版本问题而引发意外。下面是在Linux环境中重新安装Lua的方法。


$ wget -P /root https://www.lua.org/ftp/lua-5.3.5.tar.gz
$ cd /root && tar xf lua-5.3.5.tar.gz && cd lua-5.3.5
$ make all linux
$ rm -rf /usr/local/bin/lua
$ rm -rf /usr/bin/lua
$ ln -s /root/lua-5.3.5/src/lua /usr/bin/lua
$ ln -s /root/lua-5.3.5/src/lua /usr/local/bin/lua
$ lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

3.在Docker环境中安装Lua

使用Docker容器安装Lua的方法:


$ docker pull nickblah/lua:5.3.5
$ docker run -it nickblah/lua:5.3.5 /bin/bash
$ lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

安装完毕后,我们简单运行一个Hello World程序。

·用户可以在控制台先输入Lua脚本,直接进入交互模式:


> print("Hello World")
Hello World

·用户也可以选择非交互模式运行:


$ echo "print('Hello World')" > helloworld.lua
$ lua helloworld.lua
Hello World

3.1.3 解释器

解释器(Interpreter),又称为直译器,能够把高级编程语言转译并运行。它像一个中间人,每次程序运行时都要先转成另一种语言再运行。

在3.1.2节中,用户能够如此便捷地完成Hello World示例就依赖于解释器。解释器显著地提升了程序开发效率,并简化了调试步骤。在交互模式下,用户可以即时获得程序的执行结果。这种所见即所得的交互流程使得编码过程人性化、透明,也大大降低了前期编码的试错成本。

解释器也有弱势,比如相较于二进制文件或者字节码,运行速度比较慢。考量一个编程语言是否足够优秀,性能是极其重要的。Lua语言针对此问题,给出了自己的解决方案,即LuaJIT。这里展示一个简单的示例比较两者的执行效率。代码清单3-1为Lua解释器示例,代码清单3-2为LuaJIT解释器示例,代码清单3-3为两者运行时间的对比。

程序清单3-1 Lua的解释器示例


  1 #!/usr/local/bin/lua
  2 local i = 0
  3 while 1 do
  4   i = i+1
  5   ifi > 10000000 then
  6     print(i)
  7     break
  8   end
  9 end

程序清单3-2 LuaJIT的解释器示例


  1 #!/usr/local/bin/luajit
  2 local i = 0
  3 while 1 do
  4   i = i+1
  5   if i > 10000000 then
  6     print(i)
  7     break
  8   end
  9 end

程序清单3-3 运行时间对比


$ time ./lua.lua
10000001
./lua.lua  0.16s user 0.00s system 96% cpu 0.166 total
$ time ./luajit.lua
10000001
./luajit.lua  0.01s user 0.00s system 88% cpu 0.015 total

可以发现,LuaJIT解释器的执行效率为Lua解释器执行效率的10倍以上。LuaJIT还有很多其他性能优化技巧。感兴趣的读者可以自行查阅资料学习,这对我们今后进行Lua脚本开发有非常大的帮助,也是提升性能指标的关键点。

3.1.4 语法规范

大多数编程语言保留了关键字,Lua语言也不例外。这些关键字不可以用作标识符。相较于C语言,Lua语言保留的关键字比较少(仅22个),如表3-1所示。这也间接体现了Lua相对简洁的语言特征。

表3-1 Lua语言保留的关键字

标识符是由非数字开头的任意字母、下划线和数字构成的字符串。Lua语言是区分大小写的。推荐使用驼峰命名法或下划线命名法定义标识符。

注意

标识符命名风格

驼峰命名法:正如它的名称CamelCase一样,混合使用大小写字母,首字母小写,常用于面向对象语言命名。

下划线命名法:名称中的每一个逻辑端点都使用下划线分隔,常用于类C语言环境。

Lua语言的一个编译单元被称为一个代码块。从句法构成上讲,一个代码块就是一个语句块。代码块内可以定义局部变量,也可以接收参数,返回若干值,如代码清单3-4所示。

程序清单3-4 Lua语言代码块示例


> do
>>   local function foo(...)        -- 定义一个局部函数
>>     for i = 1, select('#', ...) do    -- 获取参数总数
>>       local arg = select(i, ...);    -- 局部变量读取参数
>>         print("arg", arg);
>>       end
>>     end
>>   foo(1, 2, 3, 4);
>> end
arg  1
arg  2
arg  3
arg  4

上述例子遵循着词法作用域规则。局部变量可以在它的作用范围内被定义的函数自由使用。当一个局部变量被内层的函数使用的时候,它被内层函数称作上值或者外部局部变量。每次执行到一个local语句都会定义一个新的局部变量。