暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Apisix 基础篇:OpenResty 简介

开源探索之旅 2022-02-20
2660

    在提到 OpenResty 的时候相信大部分人都是对这个词或多或少有些陌生,但是如果在云原生领域听到国外的 Kong 或国内的 Apisix 网关时,大家可能又很熟悉了,然而这两大云原生网关都是基于 OpenResty 进行开发的,所以在进一步解读 Apisix 源码之前,我们有必要先了解一下 OpenResty 这个框架。


介绍

OpenResty 

    OpenResty 是一款以 Nginx 的一个 C 模块(lua-nginx-module,该模块将 LuaJIT 嵌入到 Nginx 中,并对外提供一套完整的 Lua API)进行扩展,以 Lua 为主要开发语言的 Web 框架。


    它能够让你的 Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。


    使用户既能完美地利用 Nginx 的高性能和高并发的优势,又能拥有 Lua 脚本语言的开发效率和迭代速度。


LuaJIT 

    OpenResty 使用 LuaJIT 而不是标准 Lua 作为执行环境。


    或许有读者认为 LuaJIT 只是给 Lua 内置了一个 JIT 编译器,但实际上 LuaJIT 与 Lua 并不是一回事,LuaJIT 只是兼容了 Lua 5.1 的语法,而 Lua 目前最新版本已经更新到了 5.4,LuaJIT 的最新版本则是 2.1.0-beta3。


    在 OpenResty 几年前的老版本中,编译的时候,你可以选择使用标准 Lua VM,或者 LuaJIT VM 来作为执行环境,不过,现在已经去掉了对标准 Lua 的支持,只支持 LuaJIT。


    标准 Lua 出于性能考虑,它内置了虚拟机,所以 Lua 代码并不是直接被解释执行的,而是先由 Lua 编译器编译为字节码(Byte Code),然后再由 Lua 虚拟机去执行。


    而 LuaJIT 的运行时环境,除了一个汇编实现的 Lua 解释器外,还有一个可以直接生成机器代码的 JIT 编译器。开始的时候,LuaJIT 和标准 Lua 一样,Lua 代码被编译为字节码,字节码被 LuaJIT 的解释器解释执行。


    但不同的是,LuaJIT 的解释器会在执行字节码的同时,记录一些运行时的统计信息,并通过一些方式,找到经常被执行到的热代码,将这些热代码通过 JIT 编译器进行编译。


    编译的过程,是把 LuaJIT 字节码先转换成 LuaJIT 自己定义的中间码(IR),然后再生成针对目标体系结构的机器码,来提高这些热代码的执行效率。


    并且出于性能考虑,OpenResty 自己维护了一套 LuaJIT 分支,扩展了许多独有的 API(后续文章中提到的 LuaJIT 都指 OpenResty 自己维护的 LuaJIT 分支)。


使用


    在 上一篇 文章中,我们通过 Homebrew 安装了 OpenResty,此处以 1.19.9.1_2
 版本为例,Homebrew 会将 OpenResty 默认安装在 /usr/local/Cellar/openresty/1.19.9.1_2/
 目录下,而 OpenResty 内置的 LuaJIT 则放在 /usr/local/Cellar/openresty/1.19.9.1_2/luajit/
 目录下 。


    安装成功后,OpenResty 提供 CLI 工具 resty
 以及用来启动服务的两个命令 openresty
 和 nginx
,这两个命令完全等价,用户选择其中任意一个即可(后续文章默认都使用 openresty
),而 Apisix 的启动则是通过 openresty
 这个命令来完成的。


openresty 

    此处我们简单介绍一下 openresty
 命令。


    openresty
 命令常用的参数有 3 个。-s
-c
 以及 -p


    -s
 代表发送到 OpenResty 的指令,常用的有 stop
reload
,用来指代停止服务以及重启服务。


    -c
 是用来指定 nginx.conf
 文件具体路径的,代表启动 OpenResty 时读取哪个 Nginx 配置文件。


    -p
 是用来指定文件前缀的,在指定了文件前缀后,OpenResty 启动时则会基于该前缀去拼接对应的 Nginx 配置文件、日志文件地址等。


    在运行 openresty
 命令后,访问 localhost:80
 出现如下页面则代表 OpenResty 启动成功。



resty 

    CLI 工具 resty
 则可以用来直接执行一些比较简单的命令,如下所示。


    $ resty -e "ngx.say('hello world')"
    hello world


        前面我们提到 OpenResty 是基于 Nginx 来运行的,这个在 CLI 中也得到了很好的体现,我们来深入探究一下 CLI 命令的执行原理。


      $ resty -e "ngx.say('hello world'); ngx.sleep(60)" &


          我们使用上述命令使程序运行后进入休眠状态而不是直接退出,再来观察它背后究竟是怎样运行的。


        $ ps -ef | grep nginx
        501 14778 14776 0 11:12AM ttys010 0:00.02 usr/local/Cellar/openresty/1.19.9.1_2/nginx/sbin/nginx -p tmp/resty_VyKROmMFyF/ -c conf/nginx.conf


            它本质上就是创建了一个临时的 Nginx 配置文件并运行了 openresty -p xxx -c xxx
         (上文提到 nginx
         命令与 openresty
         命令等价)来开启了一个临时的 OpenResty 服务。而在命令退出之前,我们最后来看看 /tmp/resty_VyKROmMFyF/conf/nginx.conf
         这个文件。


          $ cat tmp/resty_VyKROmMFyF/conf/nginx.conf
          daemon off;
          # 省略部分配置


          http {
          access_log off;
          lua_socket_log_errors off;
          resolver 192.168.1.1 192.168.9.9 ipv6=off;
              lua_regex_cache_max_entries 40960;


          init_by_lua_block {
          # 省略代码
          }


          init_worker_by_lua_block {
          # 省略代码
          }
          }


              在该文件中,它初始化了两个执行阶段的代码,init_by_lua_block
           以及 init_worker_by_lua_block
          ,而这两个阶段是 OpenResty 启动时的两个初始化阶段,我们将在后续文章中进行详细解读。并且由于篇幅原因,此处省略了这两个阶段对应的代码,读者可以自行操作后进行查看。


          结束语

              本篇文章我们简单介绍了 OpenResty。当然一篇文章能描述的也只能是这个框架的冰山一角,我这里推荐感兴趣的读者阅读温铭老师写的《OpenResty 最佳实践》来做更进一步的了解。


          文章转载自开源探索之旅,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论