首先,了解一下Orange,Orange 是一个基于 OpenResty 的API网关。除 Nginx 的基本功能外,它还可用于API监控、访问控制(鉴权、WAF)、流量筛选、访问限速、AB测试、静/动态分流 等。
说句实在的,它已经实现了绝大部分的功能,只不过目前已经处于停滞状态了
项目目录结构
- api* 目测是提供的接口,官方文档中提到了该项目提供了API接口用于实现第三方服务
- bin* 应该是运行目录,里面主要是lua的一些第三方包
- conf* 配置模板,类比nginx中的配置
- dashboard* 控制台程序
- docs* 运行文档
- install* 安装方法,包含了sql语句和安装执行脚本
- orange* 也是一些Lua的代码,主要是核心代码所在地
- rockspec* 似乎是对该项目的打包,类似于java的jar一样,相当于给别人直接使用
- test* 测试库
代码分析
启动Orange
初始化
先贴代码再分析
-- 执行过程:
-- 加载配置
-- 实例化存储store
-- 加载插件
-- 插件排序
function Orange.init(options)options = options or {}local store, configlocal status, err = pcall(function()local conf_file_path = options.configconfig = config_loader.load(conf_file_path)store = require("orange.store.mysql_store")(config.store_mysql)loaded_plugins = load_node_plugins(config, store)ngx.update_time()config.orange_start_at = ngx.now()end)if not status or err thenngx.log(ngx.ERR, "Startup error: " .. err)os.exit(1)endlocal consul = require("orange.plugins.consul_balancer.consul_balancer")consul.set_shared_dict_name("consul_upstream", "consul_upstream_watch")Orange.data = {store = store,config = config,consul = consul}-- init dns_clientassert(dns_client.init())return config, store
end
不得不感叹,lua里面的匿名函数用得可针对,将方法直接作为函数的参数的方式,对编译器的词法分析器和语法分析器带来的挑战吧,有机会一定要拜读一下Lua的编译器。 首先,读取mysql的配置,然后加载配置的所有插件。
其余的内容,就是定义的插件的基本方法的调用
插件定义的关键代码
对于插件,一共有下面的几种方法
- redirect()
- rewrite()
- access()
- balance()
- header_filter()
- body_filter()
- log()
也就是重定向,重写,接收(正常处理),平衡,请求响应头处理,内容处理以及日志处理。
rewrite
redirect方法,默认的实现为:
function BasePlugin:rewrite()ngx.log(ngx.DEBUG, " executing plugin \"", self._name, "\": rewrite")
end
只是用ngx.log打印出了一个日志。 我们随便拎一个实现了该方法的插件子类来看看,这里以headers插件为例:
function HeaderHandler:rewrite(conf)HeaderHandler.super.rewrite(self)local enable = orange_db.get("headers.enable")local meta = orange_db.get_json("headers.meta")local selectors = orange_db.get_json("headers.selectors")local ordered_selectors = meta and meta.selectorsif not enable or enable ~= tru